So i have a “ship”, with “turrets” that are parented… I have a script that identifies close targets and sets them, the turrets then use these targets to coordinates to fire… problem comes in when they do not rotate correctly.
I could only guess that its…
a) because i have no idea what axis “LookAt” actually is aligning to
b) because I most likely have “local space - world space” issues
public virtual void Fire(){
Ray raycheck = new Ray(transform.position, target.transform.position);
if (!ship.GetComponent<Renderer>().bounds.IntersectRay(raycheck)){
transform.rotation = Quaternion.Slerp (transform.rotation, Quaternion.LookRotation(target.transform.position,Vector3.right), 0.7f * Time.deltaTime);
if (!IsInvoking("AttackHandler"))
Invoke("AttackHandler", 5);
}
}
public virtual void AttackHandler(){
Rigidbody Shot;
Shot = Instantiate (Ammo,mount.transform.position,Quaternion.LookRotation(target.transform.position)) as Rigidbody;
Shot.velocity = Shot.transform.TransformDirection(Vector3.forward)*200 * Time.deltaTime;
}
Quite the amount to look throught I know. on a slightly different note. what is the best way to rotate towards a target with a certain speed?
The main problem here is that you’re confusing points and vectors. Although both are stored in Vector3 structures, the meanings are different. A point is a location in the 3D space, while a vector represents a direction - think of it as an “arrow” from (0,0,0) to the vector coordinates: Vector3.up, for instance, is (0,1,0), what means a vertical arrow (from y=0 to y=1).
But there are other problems too: you’re using Quaternion.Slerp to turn gradually to the target, but this will only work if you call the Fire function each Update (or in a coroutine) - Quaternion.Slerp rotates a little each time it’s called, thus using it only once gives no noticeable effect. Another weird thing: why are you checking intersection between the ray and renderer.bounds? To avoid shooting “across” your own ship? bounds is an AABB, Axis Aligned Bounding Box, and grows or shrinks when you rotate your ship.
But lets get back to the basics: you should calculate a dir vector in the direction ship->target, what you can do just subtracting ship.position from target.position. When shooting, start a coroutine that will turn gradually to the target during duration seconds and then shoot. To avoid multiple coroutines running in the same turret, a shooting flag is used:
public virtual void Fire(){
Vector3 dir = target.transform.position-transform.position;
Ray raycheck = new Ray(transform.position, dir);
if (!ship.GetComponent< Renderer>().bounds.IntersectRay(raycheck)){
// call Shoot only when previous shot has finished
if (!shooting) StartCoroutine(Shoot(target.transform));
}
}
public float duration = 0.5f; // time in seconds to turn to target
bool shooting = false; // flag to avoid multiple Shoot calls
IEnumerator Shoot(Transform tgt){
shooting = true; // Shoot is running!
Quaternion rot0 = transform.rotation; // save initial rotation
float t = 0.0f;
while (t < 1.0f){ // turn to the target during duration seconds
t += Time.deltaTime/duration; // advance variable t
Vector3 dir = tgt.position-transform.position; // update the direction each loop
// sets rotation to an intermediate direction proportional to t:
transform.rotation = Quaternion.Slerp (rot0, Quaternion.LookRotation(dir), t);
yield return 0; // let Unity breath till the next frame
}
Rigidbody Shot;
Shot = Instantiate(Ammo, mount.transform.position, transform.rotation) as Rigidbody;
Shot.velocity = dir * 20; // shoot in the target direction
shooting = false; // Shoot has finished
}
NOTE: This is untested C# code, thus may contain some errors.