I currently have a script to move my "Player" around a surface but I find it very uneffective, the cube wiggles left to right and up and down. Does anyone have any good scrips on how to move a cube, flipping side to side, without wiggling or whatever. that also moves perfectly each time? my last one would move to a point like 2.000231 or something like that. it was really fusterating because I'm trying to have it perfect so it would fit in an hole. He's the script I am using. If you have a better one pls include ty
using System.Collections;
using UnityEngine;
public class TumblingCubes : MonoBehaviour
{
public float tumblingDuration = 0.2f;
void Update()
{
var dir = Vector3.zero;
if (Input.GetKey(KeyCode.UpArrow))
dir = Vector3.forward;
if (Input.GetKey(KeyCode.DownArrow))
dir = Vector3.back;
if (Input.GetKey(KeyCode.LeftArrow))
dir = Vector3.left;
if (Input.GetKey(KeyCode.RightArrow))
dir = Vector3.right;
if (dir != Vector3.zero && !isTumbling)
{
StartCoroutine(Tumble(dir));
}
}
bool isTumbling = false;
IEnumerator Tumble(Vector3 direction)
{
isTumbling = true;
var rotAxis = Vector3.Cross(Vector3.up, direction);
var pivot = (transform.position + Vector3.down * 0.5f) + direction * 0.5f;
var startRotation = transform.rotation;
var endRotation = Quaternion.AngleAxis(90.0f, rotAxis) * startRotation;
var startPosition = transform.position;
var endPosition = transform.position + direction;
var rotSpeed = 90.0f / tumblingDuration;
var t = 0.0f;
while (t < tumblingDuration)
{
t += Time.deltaTime;
transform.RotateAround(pivot, rotAxis, rotSpeed * Time.deltaTime);
yield return null;
}
transform.rotation = endRotation;
transform.position = endPosition;
isTumbling = false;
}
}
Your script should work just fine, you will always have small errors because of how float numbers are stored. But you shouldn't have errors as big as yours.
Are sure your cube is starting from (0,0,0)?
Anyway you can be sure if you put this in the end of the Tumble
var vec = transform.eulerAngles;
vec.x = Mathf.RoundToInt(vec.x / 90 * 90);
vec.y = Mathf.RoundToInt(vec.y / 90 * 90);
vec.z = Mathf.RoundToInt(vec.z / 90 * 90);
transform.eulerAngles = vec;
Related
I am trying to implement the seek algorithm of steering behaviors for cars. The way I have defined a path for the cars is by using spheres to signify waypoints.
I want the car to move along this waypoint using the seek algorithm. I am trying to do it in the following way. However, the car will only go to the first waypoint and get stuck there.
More specifically, my problem is that my implementation won't update wayIndex and this causes the target to never go to the next point in the waypoints array.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Follower : MonoBehaviour
{
public GameObject vehicle;
public float[] speeds = {15.0f,25.0f,35.0f};
public int pathChoice;
[SerializeField]
public Transform[] waypoints;
public Transform[] waypoints2;
[SerializeField]
public float speed;
private int wayIndex = 0;
private Vector3 target;
private Vector3 steering;
private void Start(){
int speedIndex = UnityEngine.Random.Range(0, 3);
int pathIndex = UnityEngine.Random.Range(0, 2);
speed = speeds[speedIndex];
pathChoice = pathIndex;
if (pathIndex == 0){
steering = Vector3.zero;
target = waypoints[wayIndex].position;
transform.position = waypoints[wayIndex].transform.position;
}else if (pathIndex == 1){
steering = Vector3.zero;
target = waypoints2[wayIndex].position;
transform.position = waypoints2[wayIndex].transform.position;
}
}
private void Update(){
MoveVehicle();
// transform.Rotate(-90f,0,0,Space.Self);
}
private void MoveVehicle(){
if (pathChoice == 0){
if (wayIndex <= waypoints.Length - 1){
target = waypoints[wayIndex].position;
Vector3 velocity = (target - transform.position).normalized * speed;
Vector3 seekForce = seek(target);
steering = steering + seekForce;
Vector3 finalVel = (velocity + steering);
// transform.position = Vector3.MoveTowards(transform.position,target,speed * Time.deltaTime);
transform.position = transform.position + finalVel * Time.deltaTime;
transform.LookAt(target);
// var targetRotation = Quaternion.LookRotation(target- transform.position);
// transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, speed * Time.deltaTime);
if (transform.position == waypoints[wayIndex].transform.position){
wayIndex += 1;
}
if (transform.position == waypoints[waypoints.Length - 1].position){
speed = 0.0f;
}
}
}else if (pathChoice == 1){
if (wayIndex <= waypoints2.Length - 1){
target = waypoints2[wayIndex].position;
transform.position = Vector3.MoveTowards(transform.position,target,speed * Time.deltaTime);
// var targetRotation = Quaternion.LookRotation(target- transform.position);
// transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, speed * Time.deltaTime);
transform.LookAt(target);
if (transform.position == waypoints2[wayIndex].transform.position){
wayIndex += 1;
}
if (transform.position == waypoints2[waypoints2.Length - 1].position){
speed = 0.0f;
vehicle.GetComponent<Follower>().enabled = false;
vehicle.GetComponent<Collisions>().enabled = false;
Destroy(vehicle);
}
}
}
}
private Vector3 seek(Vector3 target){
Vector3 vel = (target - transform.position).normalized * speed;
Vector3 desiredVel = (target - transform.position).normalized * speed;
Vector3 steeringForce = desiredVel - vel;
return steeringForce;
}
}
Two issues I see
You are moving your object using
transform.position = transform.position + finalVel * Time.deltaTime;
So it might happen that this overshoots the target so the check
if (transform.position == waypoints[wayIndex].transform.position)
which uses a precision range of 0.00001 never becomes true.
Before this didn't happen because MoveTowards prevents any overshooting.
You will need to use a certain range and rather approximately check
if(Vector3.Distance(transform.position, waypoints[wayIndex].transform.position) <= THRESHOLD)
where THRESHOLD needs to be a range big enough to not to be overshooten by finalVel => Something greater than the maximum finalVel magnitude
In
Vector3 vel = (target - transform.position).normalized * speed;
Vector3 desiredVel = (target - transform.position).normalized * speed;
Vector3 steeringForce = desiredVel - vel;
you store and substract the exact same vector .. your steeringForce is doomed to be always 0,0,0!
Im having a lot of weird prolems with my rigidbody collision in unity. I have a player controller script which allows me to move my player, but when it collides with stairs, it glitches out. when it collides with a door, it glitches out and when it collides with 2 nvisible box colliders at the edge of the map while walking diagonally, it walks through one of them. Ive searched around quite a bit but couldn't find anything. I know it's not a lot to go on, but here is some stuff that might help:
a video of what happens exactly
the character controller code:
using System;
using UnityEngine;
public class PlayerController : MonoBehaviour{
public Rigidbody body;
//player movement
private float speed = 12f;
private float walkSpeed = 10;
private float runSpeed = 15;
private float gravity = -9.81f;
public float jumpHeight = 2f;
private Vector3 inputs;
//player rotation
private float targetAngle = 0f;
private float angle = 0f;
public float turnSmoothTime = .1f;
public float turnSmoothVelocity;
//player jump
public Transform groundCheck;
public float groundDistance = 0.4f;
public LayerMask groundMask;
private bool isGrounded;
//there are 6 possible directions for gravity; positive and negative x, y and z. The direction can therefore be -3, -2, -1, 1, 2 or 3 where 1=y, 2=x, 3=z
public int direction = 1;
public void movePlayer(Vector2 movement){
float horizontal = movement.x;
float vertical = movement.y;
//check if the player is standing on the ground
isGrounded = Physics.CheckSphere(groundCheck.position, groundDistance, groundMask);
Quaternion rotation = new Quaternion();
body.freezeRotation = true;
if (Mathf.Abs(direction) == 1){
//gravity in y direction
//set the direction of the gravity
Physics.gravity = new Vector3(0f, direction * gravity, 0f);
//set the direction the inputs should work in
inputs.x = horizontal;
inputs.z = vertical;
inputs.y = body.velocity.y;
//calculate the angle with which the player has to be rotated and make the rotation smooth (smoothing is only possible in this orientation)
targetAngle = Mathf.Atan2(inputs.x, inputs.z) * Mathf.Rad2Deg;
angle = Mathf.SmoothDampAngle(transform.eulerAngles.y, targetAngle, ref turnSmoothVelocity, turnSmoothTime);
//set the characters rotation
rotation = Quaternion.Euler(0f, angle, 0f);
}
else if (Mathf.Abs(direction) == 2){
//gravity in x direction
Physics.gravity = new Vector3((direction / 2) * gravity, 0f, 0f);
inputs.y = -horizontal;
inputs.z = vertical;
inputs.x = body.velocity.x;
targetAngle = Mathf.Atan2(-inputs.y, inputs.z) * Mathf.Rad2Deg;
rotation = Quaternion.Euler(targetAngle, 0f, (direction / 2) * -90f);
}
else if (Mathf.Abs(direction) == 3){
//gravity in z-direction
Physics.gravity = new Vector3(0f, 0f, (direction / 3) * -gravity);
inputs.x = horizontal;
inputs.y = vertical;
inputs.z = body.velocity.z;
targetAngle = Mathf.Atan2(inputs.x, inputs.y) * Mathf.Rad2Deg;
//set the rotation in the correct order of the axis (90 degrees first and then around the correct axis)
rotation = Quaternion.AngleAxis((direction / 3) * -90f, Vector3.right) *
Quaternion.AngleAxis(0f, Vector3.forward) *
Quaternion.AngleAxis(targetAngle, Vector3.up);
}
else{
direction = 1;
}
/*
if (inputs != Vector3.zero){
body.velocity = inputs;
}*/
//rotate the player in the move direction as long as they are moving
if (inputs.magnitude >= 0.1f){
transform.rotation = rotation;
}
}
void FixedUpdate(){
//move the player
body.MovePosition(body.position + inputs * speed * Time.fixedDeltaTime);
}
public void flip(int changedDirection){
inputs = Vector3.zero;
angle = 0f;
targetAngle = 0f;
direction = changedDirection;
}
public void walk(){
if (isGrounded){
speed = walkSpeed;
}
}
public void run(){
if (isGrounded){
speed = runSpeed;
}
}
public void jump(){
if (isGrounded){
if (direction == 1){
body.velocity = new Vector3(inputs.x, jumpHeight, inputs.z);
}
else if (direction == 2){
body.velocity = new Vector3(jumpHeight, inputs.y, inputs.z);
}
else if (direction == 3){
body.velocity = new Vector3(inputs.x, inputs.y, jumpHeight);
}
}
}
}
A screenshot of my player object's important components:
P.S. the code has some weird gravty changing parts. Thats for the rest of the game, but it's not important for this question. Hopefully you guys can help me. Im happy to provide any other information you might need :) thanks for your time in advance!!
Edit: Commented out one part based on the first answer, but that din't fix it
First of all, you move your player 'twice', first inside movePlayer function you have:
//move the player
if (inputs != Vector3.zero){
body.velocity = inputs;
}
and then in every FixedUpdate:
body.MovePosition(body.position + inputs * speed * Time.fixedDeltaTime);
body.MovePosition moves yours player, but not zeroes velocity (which you set in movePlayer function).
By moving player this way you can 'overshoot' too small colider, so object will pass through.
You can add more drag to rigidbody to slowdown object a bit.
Okay so for anyone having similar problems, I found the answer:
The problem was that I was using body.moveposition, this should actually body.addforce.
This oes mean that you have to change some of the code. If you want further explanation because you had a similar problem, contact me, but here is my improved code to get you started:
using System;
using UnityEngine;
public class PlayerController : MonoBehaviour{
public Rigidbody body;
//player movement
private float speed = 12f;
private float walkSpeed = 10;
private float runSpeed = 15;
public float gravity = -9.81f;
public float jumpHeight = 2f;
private Vector3 inputs;
//player rotation
private float targetAngle = 0f;
private float angle = 0f;
public float turnSmoothTime = .1f;
public float turnSmoothVelocity;
//player jump
public Transform groundCheck;
public float groundDistance = 0.4f;
public LayerMask groundMask;
private bool isGrounded;
//there are 6 possible directions for gravity; positive and negative x, y and z. The direction can therefore be -3, -2, -1, 1, 2 or 3 where 1=y, 2=x, 3=z
public int direction = 1;
public void movePlayer(Vector2 movement){
float horizontal = movement.x;
float vertical = movement.y;
//check if the player is standing on the ground
isGrounded = Physics.CheckSphere(groundCheck.position, groundDistance, groundMask);
Quaternion rotation = new Quaternion();
body.freezeRotation = true;
if (Mathf.Abs(direction) == 1){
//gravity in y direction
//set the direction of the gravity
Physics.gravity = new Vector3(0f, direction * gravity, 0f);
//set the direction the inputs should work in
inputs.x = horizontal;
inputs.z = vertical;
inputs.y = 0;
//calculate the angle with which the player has to be rotated and make the rotation smooth (smoothing is only possible in this orientation)
targetAngle = Mathf.Atan2(inputs.x, inputs.z) * Mathf.Rad2Deg;
angle = Mathf.SmoothDampAngle(transform.eulerAngles.y, targetAngle, ref turnSmoothVelocity, turnSmoothTime);
//set the characters rotation
rotation = Quaternion.Euler(0f, angle, 0f);
}
else if (Mathf.Abs(direction) == 2){
//gravity in x direction
Physics.gravity = new Vector3((direction / 2) * gravity, 0f, 0f);
inputs.y = -horizontal;
inputs.z = vertical;
inputs.x = body.velocity.x;
targetAngle = Mathf.Atan2(-inputs.y, inputs.z) * Mathf.Rad2Deg;
rotation = Quaternion.Euler(targetAngle, 0f, (direction / 2) * -90f);
}
else if (Mathf.Abs(direction) == 3){
//gravity in z-direction
Physics.gravity = new Vector3(0f, 0f, (direction / 3) * -gravity);
inputs.x = horizontal;
inputs.y = vertical;
inputs.z = body.velocity.z;
targetAngle = Mathf.Atan2(inputs.x, inputs.y) * Mathf.Rad2Deg;
//set the rotation in the correct order of the axis (90 degrees first and then around the correct axis)
rotation = Quaternion.AngleAxis((direction / 3) * -90f, Vector3.right) *
Quaternion.AngleAxis(0f, Vector3.forward) *
Quaternion.AngleAxis(targetAngle, Vector3.up);
}
else{
direction = 1;
}
//rotate the player in the move direction as long as they are moving
if (inputs.magnitude >= 0.1f){
transform.rotation = rotation;
}
}
void FixedUpdate(){
body.AddForce(inputs * speed * Time.fixedDeltaTime);
}
public void flip(int changedDirection){
inputs = Vector3.zero;
angle = 0f;
targetAngle = 0f;
direction = changedDirection;
}
public void walk(){
if (isGrounded){
speed = walkSpeed;
}
}
public void run(){
if (isGrounded){
speed = runSpeed;
}
}
public void jump(){
if (isGrounded){
if (direction == 1){
body.AddForce(new Vector3(0, jumpHeight, 0));
}
else if (direction == 2){
body.AddForce(new Vector3(jumpHeight, 0, 0));
}
else if (direction == 3){
body.AddForce(new Vector3(0,0 , jumpHeight));
}
}
}
}
For me this created some additionl problems with jump for example, so here are the values you need to tweak to fix those: the rigidbody mass and drag and the player controller gravity and jump height.
I am working on a project in unity and I have a small circle that shows how much power will be applied to a ball and an arrow that shows the direction.
The circle and arrow are meant to scale up to a max distance; the arrow scales but it is too big (takes up half the screen) and doesn't rotate properly; the circle does not scale at all. I have tried to change the local scale of the arrow and messed around with the various values but I am not sure what to really do. The arrow tends to only face the correct direction when the cursor is in the top left and the arrow is in the bottom right.
The two points, point A and B are two empty objects; point B is attached to the ball and pointA follows the mouse. When the ball is clicked on and the cursor is dragged away pointB moves in the opposite direction; I am trying to get the arrow to face pointB at all times or point at pointB from the opposite side of the ball.
Everything except for the arrow and circle rotating and scaling works. I'm fairly new to code and don't understand Mathf.Log. The arrow rotate and scale code is commented out as I am currently trying to get the circle to work.
If you can point me in the right direction or help with just one of these issues I'd greatly appreciate it.
public class PlayerBallHit : MonoBehaviour
{
private GameObject mousePointA;
private GameObject mousePointB;
private GameObject arrow;
private GameObject circle;
// calc distance
private float currDistance;
public float maxDistance = 3f;
private float spaceLimit;
private float shootPower;
public float shootPowervar;
public Vector2 shootDirection;
void Start()
{
}
void Awake()
{
mousePointA = GameObject.FindGameObjectWithTag("PointA");
mousePointB = GameObject.FindGameObjectWithTag("PointB");
arrow = GameObject.FindGameObjectWithTag("Stick");
circle = GameObject.FindGameObjectWithTag("Circle");
}
private void OnMouseDrag()
{
currDistance = Vector2.Distance(mousePointA.transform.position, transform.position);
if (currDistance <= 3f)
{
spaceLimit = currDistance;
}
else
{
spaceLimit = maxDistance;
}
// Direction of Hit and Circle
StrDirMarkers();
// calc Power & Direction
shootPower = Mathf.Abs(spaceLimit) * shootPowervar;
Vector3 dimxy = mousePointA.transform.position - transform.position;
float difference = dimxy.magnitude;
mousePointB.transform.position = (Vector3)transform.position + ((dimxy / difference) * currDistance * -1);
mousePointB.transform.position = new UnityEngine.Vector3(mousePointB.transform.position.x, mousePointB.transform.position.y);
shootDirection = (Vector2)Vector3.Normalize(mousePointA.transform.position - transform.position);
}
void OnMouseUp()
{
//arrow.GetComponent<SpriteRenderer>().enabled =false;
circle.GetComponent<SpriteRenderer>().enabled = false;
Vector2 push = shootDirection * shootPower *-1;
GetComponent<Rigidbody2D>().AddForce(push, ForceMode2D.Impulse);
}
private void StrDirMarkers()
{
//arrow.GetComponent<SpriteRenderer>().enabled = true;
circle.GetComponent<SpriteRenderer>().enabled = true;
// calc position
/*
if (currDistance <= maxDistance)
{
arrow.transform.position = new Vector2((2f * transform.position.x) - mousePointA.transform.position.x, (2f * transform.position.y) - mousePointA.transform.position.y);
}
else
{
Vector2 dimxy = mousePointA.transform.position - transform.position;
float difference = dimxy.magnitude;
arrow.transform.position = (Vector2)transform.position + ((dimxy / difference) * maxDistance * -1);
arrow.transform.position = new UnityEngine.Vector2(arrow.transform.position.x, arrow.transform.position.y);
}
*/
circle.transform.position = transform.position + new Vector3(0, 0, 0.04f);
Vector3 dir = mousePointA.transform.position - transform.position;
float rot;
if(Vector3.Angle(dir, transform.forward)> 90)
{
rot = Vector3.Angle(dir, transform.right);
}else
{
rot = Vector3.Angle(dir, transform.right) * -1;
}
//arrow.transform.eulerAngles = new Vector3(0, 0, rot);
// scale arrow
float scaleX = Mathf.Log(1 + spaceLimit / 10000f, 2f) * 0.05f;
float scaleY = Mathf.Log(1 + spaceLimit / 10000f, 2f) * 0.05f;
//arrow.transform.localScale = new Vector3(1 + scaleX, 1 + scaleY, 0.001f);
circle.transform.localScale = new Vector3(1 + scaleX, 1 + scaleY, 0.001f);
}
}
try to use this code for scaling and rotate the arrow
Vector3 dir = mousePointA.transform.position - transform.position;
float rot;
if (mousePointA.transform.position.y >= transform.position.y)
{
rot = Vector3.Angle(dir, transform.position) * -1;
}
else
{
rot = Vector3.Angle(dir, transform.position);
}
arrow.transform.eulerAngles = new Vector3(0, 0, rot);
// scale arrow
float scaleValue = Vector3.Distance(mousePointA.transform.position,
transform.position);
arrow.transform.localScale = new Vector3(1 + scaleValue,
arrow.transform.localScale.y, 1);
circle.transform.localScale = new Vector3(1 + scaleValue * 0.05f, 1 + scaleValue *
0.05f, 0.001f);
I am working on a script to move an object back anf forth based on swipe similarly to a game called Sky Rusher on the iOS App Store. The movement in the original game lets you swipe in any direction and an object moves in the same direction. However, the object also "bounces" for lack of a better term. For example, if you swipe to the left, the object will tilt to the left and then tilt back to its original position. For the best example I can give, please take a look at this video for a demonstartion of the game:
Sky Rusher Gameplay
This is the code I currently have (the object also doesn't move back and forth when swiping, not sure what==y that is but have an idea on how to fix it):
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MovePlayer : MonoBehaviour
{
private Vector3 currentPos;
private Vector3 touchPos;
private float screenWidth;
private float screenHeight;
private float touchX;
private float touchY;
private float objectX;
private float objectY;
// Start is called before the first frame update
void Start()
{
touchX = 0;
touchY = 0;
screenWidth = (float)Screen.width / 2.0f;
screenHeight = (float)Screen.height / 2.0f;
currentPos = new Vector3(0.0f, 1.0f, 0.0f);
}
// Update is called once per frame
void Update()
{
if(Input.touchCount > 0)
{
Touch touch = Input.GetTouch(0);
if(touch.phase == TouchPhase.Moved)
{
//touchPos = new Vector3((touch.position.x - screenWidth)/screenWidth, (touch.position.y - screenHeight)/screenHeight + 1, 0.0f);
touchPos = new Vector3(touch.position.x, touch.position.y, 0.0f);
touchX = (touchPos.x - screenWidth)/screenHeight - 1f;
touchY = (touchPos.y - screenHeight)/screenHeight + 1f;
//objectX = ((currentPos.x * screenWidth) - screenWidth)/screenWidth;
//objectY = ((currentPos.y * screenHeight) - screenHeight)/screenHeight;
objectX = currentPos.x;
objectY = currentPos.y;
objectX += (touchX - objectX) * 1.5f;
//objectY += (touchY - objectY) * 1.5f;
if(touchX >= 0.9f)
{
objectX+=0.05f;
}
else if(touchX <= -0.9f)
{
objectX-=0.05f;
}
currentPos = new Vector3(objectX, objectY, 0.0f);
transform.position = currentPos;
}
}
}
void OnGUI()
{
/*
// Compute a fontSize based on the size of the screen width.
GUI.skin.label.fontSize = (int)(Screen.width / 40.0f);
GUI.Label(new Rect(20, 20, screenWidth, screenHeight * 0.25f),
"Pos: x = " + (objectX.ToString("f2")) +
", y = " + objectY.ToString("f2"));
GUI.Label(new Rect(20, 50, screenWidth, screenHeight * 0.25f),
"Touch: x = " + (touchX.ToString("f2")) +
", y = " + (touchY.ToString("f2")));
*/
}
}
I need my object to tilt when moved similarly to how it is done in sky rusher. My game is played in a landscape orientation on an iOS Device using Unity Remote 5 and Unity 2018.3.
Quick way to achieve this effect, if I understood correctly what you mean:
1) Each time touchX >= .9f (you are moving right) apply localRotation along Z axis with some angle.
2) Each time touchX <= -.9f (you are moving left) apply localRotation along Z axis with some negative angle.
To make this look smooth and not jumpy, apply rotation along several frames, first calculating target rotation, then using RotateTowards with some given speed. Here is yourr code slightly modified:
public float tiltEffectAngle = 20;
public float tiltEffectSpeed = 90f;
void Update() {
var targetRotation = Quaternion.identity;
if (Input.touchCount > 0) {
Touch touch = Input.GetTouch(0);
if (touch.phase == TouchPhase.Moved) {
//touchPos = new Vector3((touch.position.x - screenWidth)/screenWidth, (touch.position.y - screenHeight)/screenHeight + 1, 0.0f);
touchPos = new Vector3(touch.position.x, touch.position.y, 0.0f);
touchX = (touchPos.x - screenWidth) / screenHeight - 1f;
touchY = (touchPos.y - screenHeight) / screenHeight + 1f;
//objectX = ((currentPos.x * screenWidth) - screenWidth)/screenWidth;
//objectY = ((currentPos.y * screenHeight) - screenHeight)/screenHeight;
objectX = currentPos.x;
objectY = currentPos.y;
objectX += (touchX - objectX) * 1.5f;
//objectY += (touchY - objectY) * 1.5f;
if (touchX >= 0.9f) {
objectX += 0.05f;
targetRotation = Quaternion.Euler(
transform.localEulerAngles.x,
transform.localEulerAngles.y,
tiltEffectAngle);
} else if (touchX <= -0.9f) {
objectX -= 0.05f;
targetRotation = Quaternion.Euler(
transform.localEulerAngles.x,
transform.localEulerAngles.y,
-tiltEffectAngle);
}
currentPos = new Vector3(objectX, objectY, 0.0f);
transform.position = currentPos;
}
}
transform.localRotation = Quaternion.RotateTowards(transform.localRotation, targetRotation, tiltEffectSpeed * Time.deltaTime);
}
I currently have code to move my "Player" around a surface using arrow keys, but I find the cube wiggles and doesn't move perfectly. So after a couple movements the coordinates are never perfect. Always something like 90.0012 or something related when I wanted it to be 90 per say. anyone have any suggestions? here's the code:
using System.Collections;
using UnityEngine;
public class TumblingCubes : MonoBehaviour
{
public float tumblingDuration = 0.2f;
void Update()
{
var dir = Vector3.zero;
if (Input.GetKey(KeyCode.UpArrow))
dir = Vector3.forward;
if (Input.GetKey(KeyCode.DownArrow))
dir = Vector3.back;
if (Input.GetKey(KeyCode.LeftArrow))
dir = Vector3.left;
if (Input.GetKey(KeyCode.RightArrow))
dir = Vector3.right;
if (dir != Vector3.zero && !isTumbling)
{
StartCoroutine(Tumble(dir));
}
}
bool isTumbling = false;
IEnumerator Tumble(Vector3 direction)
{
isTumbling = true;
var rotAxis = Vector3.Cross(Vector3.up, direction);
var pivot = (transform.position + Vector3.down * 0.5f) + direction * 0.5f;
var startRotation = transform.rotation;
var endRotation = Quaternion.AngleAxis(90.0f, rotAxis) * startRotation;
var startPosition = transform.position;
var endPosition = transform.position + direction;
var rotSpeed = 90.0f / tumblingDuration;
var t = 0.0f;
while (t < tumblingDuration)
{
t += Time.deltaTime;
transform.RotateAround(pivot, rotAxis, rotSpeed * Time.deltaTime);
yield return null;
}
transform.rotation = endRotation;
transform.position = endPosition;
isTumbling = false;
}
}
The problem occurs because of precision problem with float variables. Google about float calculation problem or something similiar and you will get the point. Doing many multiplications and divisions on floats usually results in some accuracy flaws, as there's more and more aproximation in results.
Solution
To solve the problem you shoul round the endPosition. There's many ways to do that, for example:
endPosition = new Vector3((int)endPosition.x, (int) endPosition.y, (int) endPosition.z);
or
endPosition.x = (int)endPosition.x;
endPosition.y = (int)endPosition.y;
endPosition.z = (int)endPosition.z;