GameObject is vibrating throughout the movement - unity3d

I have a GameObject that takes position coordinates from a file. This GameObject moves with vibration rather than smoothly. (as if moving back and forth.)
Here is the code that provides the movement:
int counter = 0;
void Update()
{
var maxDistance = speed_* Time.deltaTime;
var oldPosition = transform.position;
var newPosition = Vector3.MoveTowards(transform.position, positions[counter], maxDistance);
var actualDistance = Vector3.Distance(newPosition, oldPosition);
var distanceRemainder = maxDistance - actualDistance;
if (distanceRemainder > 0.0001)
{
newPosition = Vector3.MoveTowards(newPosition, positions[counter], distanceRemainder);
counter++;
}
transform.localPosition = newPosition;
}
NOTE: The data read from the file is in the "positions" array (x,y,z coordinates).
When I lower the 300f value in the variable maxDistance, the vibration stops and the motion becomes more fluid. However, Gameobject speed is also slowing down. How can I ensure a fast and smooth movement?
SOLUTION:
While looking for a solution of the problem, I came across the this topic. It helped me learn the source of the problem.
I have observed that the GameObject is not vibrating in Scene view, it was moving smoothly. But the object seemed to be vibrating in GameView. The problem is not the moving object, it's the camera function I write to follow it.
The camera function that was written to follow the object has been updated and the problem has disappeared.
One can see more of the solution by going to Post #13 in the link above.
Thanks to everyone trying to help.

This is caused cause you are using your distanceRemainder as your maxDistanceDelta, which I think is incorrect, if you want a smooth movement, you should multiply it for the Time.deltaTime, try:
newPosition = Vector3.MoveTowards(newPosition, positions[counter], distanceRemainder*Time.deltaTime);
Or simply declare speed variable and do:
newPosition = Vector3.MoveTowards(newPosition, positions[counter], speed*Time.deltaTime);

I assume what you want is your object moving with a constant speed to the first position. Once it reaches it, move to the next one.
I would do it in a simple Coroutine which is better to understand and maintain than doing stuff in Update:
private void Start()
{
// todo assign positions
StartCoroutine(RunPositions());
}
private IEnumerator RunPositions()
{
foreach(var position in positions)
{
while(!Mathf.Approximately(Vector3.Distance(transform.position, position), 0))
{
var maxDistance = speed_* Time.deltaTime;
transform.position = Vector3.MoveTowards(transform.position, positions[counter], maxDistance);
// render and continue in the next frame
yield return null;
}
}
}
If you are fine with a precision of 0.00001 you can also simply use
while(transform.position != position)
instead.

Related

turning towards an object in Unity

Good times. How do I implement the NPC rotation towards the selected object?
public GameObject BufferObject;
public float MoveSpeed = 1f;
void Update()
{
float step = MoveSpeed * Time.deltaTime;
transform.position = Vector2.MoveTowards(transform.position, BufferObject.transform.position, step);
}
Here is the script for moving the NPC to the selected object (Buffer Object) and the movement works perfectly, but the implementation of the rotation causes Me difficulties, please advise.
For Unity2D.
Simply get the desired direction
var direction = (BufferObject.transform.position - transform.position).normalized;
and then the desired rotation using Quaternion.LookRotation like e.g.
var targetRotation = Quaternion.LookDirection(direction);
Then either apply it directly if you want it immediately
transform.rotation = targetRotation;
Or if you want it smooth you could use e.g. Quaternion.RotateTowards like
transform.rotation = Quaternion.RotateTowards(transform.rotation, targetRotation, anglePerSecond * Time.deltatime);
Have in mind though that it might look awkward if the rotation is too slow since your NPC could move back/sidewards already while still not fully looking towards the target ;)
So you might want to wait until
if(Quaternion.Angle(targetRotation, transform.rotation) <= certainThreshold)
{
... your movement code
}
So the answer and the solution from Me, albeit stupid, but working. In order to reflect the sprite, you need to get a variable, either 1 or -1 (For Scale). This code will show the distance from one NPC to the object:
BufferObject.transform.position.x - transform.position.x
And here I get a lot of values as if to the left of the NPC, then -x... , and if to the right, then x... thereby it is possible to determine which side of the object, so also level the value from here (Optional) to 1 or -1 and apply this result to transform.localScale and thereby solve the problem of how to reflect (Rotate the sprite) towards the object. Use it for your health :)
Complete code:
float localPositionAmount = BufferObject.transform.position.x - transform.position.x;
if (localPositionAmount >= 1)
{
gameObject.transform.localScale = new Vector3(1, transform.localScale.y, transform.localScale.z);
}
if (localPositionAmount <= -1)
{
gameObject.transform.localScale = new Vector3(-1, transform.localScale.y, transform.localScale.z);
}
if (localPositionAmount == 0)
{
gameObject.transform.localScale = new Vector3(transform.localScale.x, transform.localScale.y, transform.localScale.z);
}
Yes, the code is the simplest and without enumerations and other things, but it works perfectly. I still had to figure it out myself...

Player stops move the character direction resets [Unity 2D]

My character is a car and I try to rotate it the direction it move, so far so good I succeeded to do that but once I stop moving the character flips back to the direction it was on the start.
Also how can I make my turns from side to the opposite site smooth ?
Here is my code so far:
[SerializeField] float driveSpeed = 5f;
//state
Rigidbody2D myRigidbody;
// Start is called before the first frame update
void Start()
{
myRigidbody = GetComponent<Rigidbody2D>();
}
// Update is called once per frame
void Update()
{
Move();
}
private void Move()
{
//Control of velocity of the car
float HorizontalcontrolThrow = CrossPlatformInputManager.GetAxis("Horizontal"); // Value between -1 to 1
float VerticalcontrolThrow = CrossPlatformInputManager.GetAxis("Vertical"); // Value between -1 to 1
Vector2 playerVelocity = new Vector2(HorizontalcontrolThrow * driveSpeed, VerticalcontrolThrow * driveSpeed);
myRigidbody.velocity =playerVelocity;
**//Direction of the car**
Vector2 direction = new Vector2(HorizontalcontrolThrow, VerticalcontrolThrow);
float angle = Mathf.Atan2(direction.y, direction.x) * Mathf.Rad2Deg;
myRigidbody.rotation = angle;
}
I'm not sure about this, but maybe that last line "myRigidbody.rotation = angle" being called every frame is what is making your car reset its rotation.
Maybe change it to "myRigidbody.rotation *= angle" or "myRigidbody.rotation += angle".
It looks like it may be because HorizontalcontrolThrow and VerticalcontrolThrow are going to be reset when you release the controls. If it's resetting to its original orientation, then what's happening is that until you move, those two values are going to be at their default value. You then move and it affects the rotation. But when you release the controls, those values are back to the starting values again, and so is your rotation.
What you therefore need to do is try to separate the HorizontalcontrolThrow and VerticalcontrolThrow from the rest of the code, which should only be activated when at least one of these two variables are not at their default setting (I can't remember what the axis functions return at the moment).
Edit:
An IF statement should suffice (some rough pseudo code):
if (horizontalAxis != default || verticalAxis != default)
{
Rotate/Move
}
I solved the snap rotation using Quaternion at rotation, the issiu I had with it was to convert it from 3d to 2d, through the guide of this clip: youtube.com/watch?v=mKLp-2iseDc and made my adjustments it works just fine !

Camera Move and Rotate Follow Player very jerky

I make a character move on the surface of a circle. I let the camera move and rotate follow character. But the camera move and rotate very jerky. If I increase the value of the third parameter, the shock increases. and to reduce the value of the third parameter, the camera does not rotate to keep up the character. Help me fix it
My Code Camera Follow Player
public class CameraFollow : MonoBehaviour
{
public Transform player;
GameController gc;
public float speed = 2;
Vector3 pos = new Vector3 (0, 0, -10);
// Use this for initialization
void Start ()
{
gc = FindObjectOfType (typeof(GameController)) as GameController;
}
void FixedUpdate ()
{
if (gc.gameState == GameController.GameState.playing || gc.gameState == GameController.GameState.changeWave) {
transform.position = player.position + pos;
transform.rotation = Quaternion.Slerp (transform.rotation,
player.transform.rotation,
speed * Time.deltaTime);
}
}
}
Setting the position of a transform inside of FixedUpdate is a red flag for sure, especially when you're reporting that it's "jerky". Fixed update happens at an irregular interval compared to the frames displayed. This is because Physics needs to update using a fixed time step. The reason why this is the case is out of scope for this question.
Long story short, try changing FixedUpdate to Update and that should fix things looking "jerky".
Let me know if this doesn't work and I'll look for other possible causes.
If you are using a Rigidbody2D to move the character, make sure to set its Interpolate property to 'Interpolate'. This should fix it.

Move an object in unity2D towards another clicked object

I have an object called 'Player' in my scene.
I also have multiple objects called 'Trees'.
Now I'd like whenever the user clicks on a 'Tree', the 'Player' to move slowly to that position (using Lerp or moveTowards) is both O.K for me.
Now I have 2 issues with this code:
I'd like this code to be generic
Whenever I click a tree object I'd like this to move the player towards that tree. I don't want to write up this script and attach it to each tree object.
Where should I put the script?
Currently I attach this code to every tree object.
How should I write it down so that it applies to every tree object
in the scene?
If another click is made while moving, cancel previous movement and start moving to new position
How should I write it so that if I click on another object while the
player is moving towards another object that was clicked, the players stops moving towards it's previous position, and starts
moving towards the new point.
I'm having some trouble adjusting to the new UnityScript thingy. I come strictly from a Javascript background and it really seems like the 2 of them are languages with very different semantics. So if someone answers this with code(which is what I would want:) ), I'd appreciate some verbose comments as well.
I currently do this:
var playerIsMoving = false;
Public playerObject: Gameobject; //I drag in the editor the player in this public var
function update(){
var thisTreePosition = transform.point; //this store the X pos of the tree
var playerPosition = player.transform.point;
if(playerIsMoving){
player.transform.position = Vector2.MoveTowards(playerPosition, thisTreePosition, step);
}
}
function OnMouseDown(){
playerIsMoving = true;
}
I'm writing this from home where I don't have Unity and I forgot the code syntax therefore expect the above code to have typos or issues, at work it works just fine, apart from being very crude and unsophisticated.
I would recommend you to put the movement Script on the player. And how abour using Raycast to the test whether you hit a tree?
http://docs.unity3d.com/ScriptReference/Physics.Raycast.html
Vector3 positionToWalkTo = new Vector3();
void Update() {
if (Input.GetMouseButtonDown(0)) {
RaycastHit hit;
Ray ray = new Ray(transform.position, direction);
if (Physics.Raycast(ray, out hit))
if (hit.gameObject.tag.Equals("tree")){
positionToWalkTo = hit.gameObject.transform.position;
}
}
float step = speed * Time.deltaTime;
transform.position = Vector3.MoveTowards(transform.position, positionToWalkTo, step);
}
To get something like this running, you should tag all the trees.
'JavaScript'
var target: Transform;
// Speed in units per sec.
var speed: float;
function Update () {
if (Input.GetMouseButtonDown(0)) {
var hit: RaycastHit;
var ray = Camera.main.ScreenPointToRay (Input.mousePosition);
// Raycasting is like shooting something into the given direction (ray) and hit is the object which got hit
if (Physics.Raycast(ray, hit)) {
if (hit.gameObject.tag = "tree")
target = hit.gameObject.transform.position; // Sets the new target position
}
}
// The step size is equal to speed times frame time.
var step = speed * Time.deltaTime;
// Move our position a step closer to the target.
transform.position = Vector3.MoveTowards(transform.position, target.position, step);
}
Okay, so I've done it myself (with some help from Freshchris's answer).
Here it is:
var target:Vector2;
var targetObject:GameObject;
var initialY:float;
var tolerance = 1;
var speed = 3;
var isMoving = false;
function Start(){
target = transform.position;
}
function Update () {
if (Input.GetMouseButtonDown(0)) {
var hit: RaycastHit2D = Physics2D.Raycast(Camera.main.ScreenToWorldPoint(Input.mousePosition), Vector2.zero); //raycast the scene
// if we hit something
if (hit.collider != null) {
isMoving=true; //it should start moving
targetObject = hit.collider.gameObject; //the target object
target = hit.collider.gameObject.transform.position;
}
}
// The step size is equal to speed times frame time.
var step = speed * Time.deltaTime;
// if it should be moving - move it - and face the player to the correct direction
if (isMoving){
if(transform.position.x>target.x){
gameObject.transform.localScale.x = -0.7;
}else {
gameObject.transform.localScale.x = 0.7;
}
transform.position = Vector2.MoveTowards(transform.position, target, step);
}
// if it reached the target object by a specified tolerance, tell it to stop moving
if(isMoving){
if((transform.position.x < target.x+tolerance)&&(transform.position.x > target.x-tolerance)){
print("position reached"); //this is fired just once since isMoving is switched to false just one line below
print(targetObject);
isMoving=false;
}
}
}

Unity 3D game jumping randomly

I am developing my first game with the Unity3D engine and I have run into my first problem! Not as exciting as I thought. If I spam the jump button w my ball jumps the first time then when it lands it does not jump right away but it jumps randomly after a number of button presses. The code I am using is below.
#pragma strict
var rotationSpeed = 100;
var jumpHeight = 8;
private var isFalling = false;
function Update ()
{
//Handle ball rotation.
var rotation : float = Input.GetAxis ("Horizontal") * rotationSpeed;
rotation *= Time.deltaTime;
rigidbody.AddRelativeTorque (Vector3.back * rotation);
if (Input.GetKeyDown(KeyCode.W) && isFalling == false)
{
rigidbody.velocity.y = jumpHeight;
}
isFalling = true;
}
function OnCollisionStay ()
{
isFalling = false;
}
I heard this was a arithmetic behavior problem in UnityScript. I am a very beginner at programming and do not really understand the code in UnityScript and this is the first game/project I am making in Unity3D. Help would be greatly appreciated. Thanks!
You would think that something as simple as jumping should be a no-brainer, but there are a couple of gotchas here:
It can happen that Update() is called twice without any physics updates in between. This means you don't receive OnColliderEnter nor OnColliderStay in between but you still reset isFalling, blocking the jump key.
The moment the ball hits you will receive OnColliderEnter, but not OnColliderStay. This won't happen until the next physics update. If you only listen to -stay you will be one update late.
If you press jump right at the time the ball is supposed to hit the ground then your key is already down when the first collider hit registers. You will be another update late.
Objects sink a little bit into the collider. When you jump, it might take a couple of updates before you clear the collider and you will receive OnColliderStay after you jumped.
I think that last point is the biggest problem here. To solve this you need to do a couple of things:
Use both OnColliderEnter and OnColliderStay. This will imrpove your timing with one update.
Reset isFalling in FixedUpdate instead of in Update. FixedUpdate is part of the physics loop, so it is called right before OnCollisionEnter and OnCollisionStay who will set it again immediately if needed.
Remember that you are trying to jump until you are actually in the air. This allows you to clear the collider with one button press.
The code below implements these points. If you want the timing to be even tighter you must queue the next jump while you are in the air.
#pragma strict
var rotationSpeed = 100;
var jumpHeight = 8;
private var isFalling = false;
private var tryingToJump = false;
function Update ()
{
//Handle ball rotation.
var rotation : float = Input.GetAxis ("Horizontal") * rotationSpeed;
rotation *= Time.deltaTime;
rigidbody.AddRelativeTorque (Vector3.back * rotation);
if (Input.GetKeyDown(KeyCode.W) && !isFalling) tryingToJump = true;
if (tryingToJump)
{
if (isFalling) tryingToJump = false;
else rigidbody.velocity.y = jumpHeight;
}
}
function FixedUpdate()
{
isFalling = true;
}
function OnCollisionStay()
{
isFalling = false;
}
function OnCollisionEnter()
{
isFalling = false;
}