Home Unity

Simple Unity Distance Problem

Voltage3000
polycounter lvl 6
Offline / Send Message
Voltage3000 polycounter lvl 6
Hi guys. I'm a Unity noob, and a general coding noob, but I'm trying to jump into it. I'm trying to make this top down strategy game where you can switch between units and move with the arrow keys and mouse. The issue I'm running into is that when the player runs into the mouse it starts flipping around, which makes sense. I'm trying to fix it by stoping it from turning when the cursor gets too close to the character. The problem is both sqrMagnitude and Vector3.distance don't seem to be acting the way I expect them to. If the character isn't moving the distance doesn't change and it's calculated incorrectly when I do move the character.

I've got a video of what happens here. The distance is what is getting printed in the console in the corner supposedly
https://vimeo.com/108958660

and this is the code I was using. The script is how I control all the characters
public class rb_controller2 : MonoBehaviour {

	private Animator anim;							// a reference to the animator on the character
	public float MoveSpeed;
	//public float acc;
	Rigidbody rb;
	public Plane playerPlane;
	public Ray ray;
	string player = "a";
	public GameObject clicker;
	public GameObject playerA;
	public GameObject playerB;
	public GameObject playerC;
	GameObject active_player;

	
	// Use this for initialization
	void Start () {
		active_player = playerA;
		anim = GetComponent<Animator>();
		rb = GetComponent<Rigidbody>();
		//freezes rotation along these axis in general, but not due to physics
		rb.constraints = RigidbodyConstraints.FreezeRotationX;
		rb.constraints = RigidbodyConstraints.FreezeRotationZ;
		//freezes rotation due to physics
		rb.freezeRotation = true;
	}


	// Update is called once per frame
	void Update () {
		if(Input.GetKeyDown(KeyCode.Alpha1)){
			player = "a";
			active_player = playerA;

		}
		if(Input.GetKeyDown(KeyCode.Alpha2)){
			player = "b";
			active_player = playerB;
		}
		if(Input.GetKeyDown(KeyCode.Alpha3)){
			player = "c";
			active_player = playerC;
		}
	
		float Zspeed = transform.InverseTransformDirection(rb.velocity).z;
		anim.SetFloat("speed", (Zspeed));

	
			if(gameObject.CompareTag(player)){
				[COLOR="Red"][B]//calculate distance[/B][/COLOR]
				float distance = Mathf.Sqrt(Mathf.Abs((clicker.transform.position - active_player.transform.position).sqrMagnitude));
				Debug.Log(distance);
				rb.angularDrag = 1;
				//control rotation
				//convert mouse pos to raycast and line up with plane
				playerPlane = new Plane(Vector3.up, transform.position);
				ray = Camera.main.ScreenPointToRay (Input.mousePosition);
				float hitdist;
				//get rotation
				if (playerPlane.Raycast(ray, out hitdist)) {
					Vector3 targetPoint = ray.GetPoint(hitdist);
					Quaternion targetRotation = Quaternion.LookRotation(targetPoint - transform.position);
					//rotate
					transform.rotation = targetRotation;
				}
				

			anim.SetBool("attack",(false));
			if(Input.GetKey(KeyCode.W)){
				rb.velocity = transform.forward * MoveSpeed;
			}

			if(Input.GetKey(KeyCode.S)){
				rb.velocity = (-transform.forward * MoveSpeed)*.7f;
			}

			if(Input.GetKey(KeyCode.Space)){
				anim.SetBool("attack", (true));
			}

			}
			else{
				print("no_input");
				rigidbody.velocity = Vector3.zero;
				rigidbody.angularVelocity = Vector3.zero;
			}
		}



	}
Have any of you had similar issues? I'm kind of out of ideas for what to tinker with.

Replies

  • SanderDL
    Offline / Send Message
    SanderDL polycounter lvl 7
    I think maybe you are making caluclation the distance to complicated. Take a look at:

    http://docs.unity3d.com/ScriptReference/Vector3-sqrMagnitude.html

    It might point you in the right direction.
  • Voltage3000
    Offline / Send Message
    Voltage3000 polycounter lvl 6
    Hi, sorry for the long response time. I'm kindof juggling 20 different things right now. So if I do just (clicker.transform.position - active_player.transform.position).sqrMagnitude or just vector3.distance(clicker.transform.position, active_player.transform.position) I get similar results just a different magnitude of number. I feel like it has something to do with me switching out the game object active_player. I'm going to keep looking at it obviously, but any help is greatly appreciated.
  • Farfarer
    So, as I understand it, the clicker is the red box? If so, where is it's position getting updated for you to take the distance from it to the player?

    Also, you're referencing transform.position and transform.rotation in that code... which is going to give you the transform of the GameObject that this script is applied to. I expect you're after the transform of the player character.

    You don't need to do square root of the square magnitude of the absolute of a vector subtraction.

    The square of anything is always positive, so you don't need abs. There is a magnitude value (rather than sqrMagnitude) that will do the square root for you.
    float distance = (clicker.transform.position - active_player.transform.position).magnitude;
    

    And you should really be caching references to the transforms, because it's really expensive to have to look them up every single frame.



    EDIT: And code tags, please.
  • Voltage3000
    Offline / Send Message
    Voltage3000 polycounter lvl 6
    apologies, didn't know about code tags, wondered how people got it to display like that. Thanks for your help. My code is now
    float distance = (clicker.transform.position - active_player.transform.position).magnitude;
    
    and it appears to be working now. however, I fixed the flipping problem by changing the code for rotation to
    Quaternion newRotation = Quaternion.LookRotation(clicker.transform.position - transform.position, Vector3.up);
    				newRotation.x = 0.0f;
    				newRotation.z = 0.0f;
    				transform.rotation = Quaternion.Slerp(transform.rotation, newRotation, Time.deltaTime * 8);
    


    which smooths out the motion so it doesn't look like its teleporting around, and seems to look better in general to me.

    What do you mean caching references to transforms? I'm unfamiliar with the term.

    Also you said,
    Also, you're referencing transform.position and transform.rotation in that code... which is going to give you the transform of the GameObject that this script is applied to. I expect you're after the transform of the player character.

    Since I'm only running the code if the player's tag is equal to the player string variable shouldn't I only get the position of the player character? Or is that not a good way to do it?
  • SanderDL
    Offline / Send Message
    SanderDL polycounter lvl 7
    I think what Farfarer means is that you should make a variable that contains your target.

    Then you can just assign it once and then it doesn't have to look up what the transform is every frame.
    myTarget = this.transform
    
    or something like that.
  • Farfarer
    Yep, just like that - assign a variable to the transforms and use those to access them.

    Essentially it's storing a direct reference to the transform component. Otherwise it has to look up the transform component every time you use myGameObject.transform.position. Instead you'd use myGameObjectTransform.position and it's already been looked up and stored in that variable, so it's a lot faster.
    Transform myGameObjectTransform = myGameObject.transform;
    myGameObjectTransform.position = ...;
    ...
    
Sign In or Register to comment.