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
http://docs.unity3d.com/ScriptReference/Vector3-sqrMagnitude.html
It might point you in the right direction.
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.
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.
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,
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?
Then you can just assign it once and then it doesn't have to look up what the transform is every frame. or something like that.
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.