General Math Questions

edited in Questions and Answers
So, I have some mathematical questions I cannot get my tired brain around, and this is something I need for 2 separate projects, so here goes.

I am working on a space fighter of sorts and I'm trying to make a targeting system where you select what to attack and your ship manages the turning and firing for you, this has turned into something somewhat troublesome for me, and I cannot think of (or find) a good strategy to pull this off. Mathematically speaking I guess the problem is simple:
vector myPosition, myTarget, direction

vector targetDirection = (myTarget - myPosition).normalized

turn direction towards targetDirection


Im getting some really weird behaviours with the turn size changing arbitrarily and having random small loops (my target is sitting at 0,0,0 while I try work this out). I have tried lerping values with correct wrapping and I have tried Unity's Vector3.RotateTowards and I cannot get the right values for this to feel right.

What would be some good/interesting/potential solutions I could employ to make it feel like the ship is actually flying around?

I currently have random rotation and other things that aren't the desired effect, and my previous results (the fig-8) weren't promising:

imageimage

The code I am using is the following:
public class ShipFlight : MonoBehaviour {

	public Vector3 direction = new Vector3();
	public Vector3 targetDirection = new Vector3();

	public Vector3 target = new Vector3();
	public float speed = 1;

	// Use this for initialization
	void Start () {

	}
	
	// Update is called once per frame
	void Update () {

		speed = Mathf.Clamp (speed, 1, 10);

		targetDirection = (target - gameObject.transform.position).normalized;

		direction = Vector3.RotateTowards (direction, targetDirection, Mathf.PI / 360, 0.1f).normalized;

		gameObject.transform.Translate (speed * direction * Time.deltaTime);

		gameObject.transform.LookAt (gameObject.transform.position + direction);
	}
}

Which gives me the results in the first image, the ship randomly chooses a rotate direction and flies around erratically - however admittedly every now and then hitting the correct target.

In the image below you can see my targets and target direction seem to go towards the correct values (however this particular instance the ship got stuck flying past 0,0,0 in a straight line):
image

If there is some technique I can apply here that would be great, I am at a bit of a loss.
space.PNG
464 x 508 - 49K
space 2.PNG
815 x 839 - 327K
Around0zero.PNG
837 x 450 - 42K

Comments

  • edited
    My gut tells me your order of operations is wrong. Why don't you just rotate the ship towards the target (lerp it if you want) and then fly only forward (transform.forward) rather than translating and then rotating. That should make your ship curve towards the target, spiralling in if you lerp the rotation too slowly.

    public class Ship : MonoBehaviour {
    
    	public float speed = 10.0f;
    	public Transform target;
    
    	void Update () {
    		transform.LookAt(target.position);
    		transform.position += transform.forward * speed * Time.deltaTime;
    	}
    }
  • edited
    Here's an example with lerping the rotation. In this instance, the ship flys through the target and then banks and turn around to fly through again.

    public class Ship : MonoBehaviour {
    
    	public float speed = 10.0f;
    	public float turnSpeed = 1.0f;
    	public Transform target;
    
    	void Update () {
    		var targetDirection = target.position - transform.position;
    		var newDirection = Vector3.RotateTowards(transform.forward, targetDirection, turnSpeed * Time.deltaTime, 0.0f);
    		transform.rotation = Quaternion.LookRotation(newDirection);
    
    		transform.position += transform.forward * speed * Time.deltaTime;
    	}
    }
  • The problem with LookAt is it is an immediate action, it doesn't turn towards the object, it just changes direction immediately to where you look. Will try the second example too but at a glance it looks like it just immediately turns to face the target with no lerp at all.
  • The second example is constrained from turning directly towards the target by the 3rd parameter which is maxRadians. There I'm using a configurable turnSpeed value & time.

    In a test where the target was a original and the ship at (5,10,-20) I could happily play with turnSpeed values between 0.1 and 1
  • Would strongly suggest reading up about steering behaviors and seeing how the various implementations of Boids maneuver towards targets. This is solved, you just need the right place to look :)
  • There's always the seminal work by Craig W. Reynolds on steering behaviors
  • edited
    @edg3 here's my tracking AI for some turrets I posted about a while back.

    I needed my turrets to gradually track towards the player...

    It kicks off when you get in range, and it shoots at you when you are even closer...
    Same code is applied to different enemies (mines, bouncers and lazers)

    It can be seen in action here...

    http://makegamessa.com/discussion/1998/prototype-random-space-procedural-level-generation#Item_6

    Here's the code... (maybe something useful in there)

    See the Quaternion.RotateTowards bit... the Immediate Lookat also baffled me at first and looked unnatural.

    Edit: Its a 2d Game so I only rotate on the Z... but could be adjusted.

    private void Track()
    	{
    		if (!playerInLineofSight)
    			return;
    
    		//AIM
    		var direction = target.transform.position - transform.position;
    
    		//Immediate lookat
    		//this.transform.LookAt(transform.position + new Vector3(0,0,1), direction);
    
    		//smooth/slow rotate
    		float rotateSpeed = 150f;//default
    			
    		if (IsMine||IsBouncer)
    			rotateSpeed = rotateSpeed * 10;
    		else if(IsEnemy)
    			rotateSpeed = rotateSpeed * 11;
    		else if(IsLazer)
    			rotateSpeed = rotateSpeed * 12;
    
    		//smooth rotation over time
    		float step = rotateSpeed * Time.deltaTime;
    		var targetRotation = Quaternion.LookRotation(direction, Vector3.back);
    		targetRotation.x = 0.0f;
    		targetRotation.y = 0.0f;
    		transform.rotation = Quaternion.RotateTowards(transform.rotation, targetRotation, step);
    
    		//MOVEMENT
    		float speed = 0.4f;
    		if (playerInShootRange) 
    		{
    			if(IsMine)
    				gameObject.rigidbody2D.AddForce(direction * speed);
    
    			if(IsEnemy)
    				gameObject.rigidbody2D.AddForce(direction * speed*1.2f);
    		}
    	}
  • What was getting me is the rotation on 3 axes didn't seem to want to work fine for me. What @aodendaal posted (second post) works perfectly, I misread it initially. Using a direction vector is also, as it turns out, much more annoying than just using the transform.forward vector.

    Eye candy for results:
    image

    image
    SpaceGame1.PNG
    1286 x 895 - 1024K
    SpaceGame2.PNG
    1851 x 894 - 2M
    Thanked by 1konman
  • edited
    oooh pretty! could you share your technique for those trails? It reminds me of Homeworld a little bit.
  • Those trails are actually built into Unity (Trail Renderer) - I want to tackle my own trails eventually, for now not so much.
  • @edg3 much drool... What are you doing with this? Are you working on some sort of space combat game? Those images look epic!
Sign In or Register to comment.