The title line captures the essentials of my problem.
Will post code.
These are the details; when I run my project and the missile (which has Bullet.Cs component attached to it) passes in to the Radar trigger, the turret should turn and aim at its calculated intercept point. My calculation is however wrong (I get NaN’s and Infinities) because for some reason the code that accesses a Property in my Bullet.cs class accesses it before the Start() function gets called for Bullet.cs! This results in my TopVelocity property being zero, which causes an illegal operation when I try to divide by it.
I’m not sure how to fix this.
My code:
using UnityEngine;
public class Turret : Spawnable
{
public float turnSpeed = 1f, refireRate = 0.2f;
public bool isTracking = false;
Quaternion elevation, rotation, defaultElevation, defaultRotation;
public Transform turretBase, turretGun, looker, bulletSpawn;
Vector3 intercept;
Bullet bScript, tScript; //Bullet and Target Bullet.cs scripts
public GameObject bGO; //Bullet prefab
Rigidbody tRB; //Target RigidBody
public GameObject radarField;
Timer refireTimer;
new public void Start()
{
base.Start();
defaultElevation = turretGun.rotation;
defaultRotation = turretBase.rotation;
refireTimer = gameObject.AddComponent<Timer>();
refireTimer.Limit = refireRate;
intercept = new Vector3();
bScript = bGO.GetComponent<Bullet>();
}
void Calculate()
{
float t1, magnitude;
magnitude = tScript.FixedAcceleration * Mathf.Pow(Time.realtimeSinceStartup, 2f); //Find magnitude
t1 = magnitude / bScript.TopVelocity;
intercept = t1 * tRB.velocity.normalized + tRB.position;
turretBase.LookAt(intercept);
}
public void Traverse()
{
if (isTracking)
{
/*NOTE: This code is commented out because I am having a beefin time trying to get the turret to point at the target atm. So I'm just using the LookAt() function above in Calculate()*/
//turretGun.localRotation = elevation;
// Quaternion.RotateTowards(turretGun.localRotation, elevation, turnSpeed);
/* turretBase.localRotation = rotation; //These Have to stay local or otherwise I must adjust the x axis of the base by 90 degrees.
turretGun.localRotation = elevation;
*/ //Quaternion.RotateTowards(turretBase.rotation, rotation, turnSpeed);
}
else
{
// turretGun.localRotation = Quaternion.Slerp(turretGun.localRotation, defaultElevation, turnSpeed);
// turretBase.rotation = Quaternion.Slerp(turretBase.rotation, defaultRotation, turnSpeed);
}
}
public void SetTarget(GameObject t)
{
if (t != null)
{
tRB = t.GetComponent<Rigidbody>();
tScript = t.GetComponent<Bullet>();
isTracking = true;
print("Got target!");
refireTimer.Begin();
}
else
{
isTracking = false;
intercept = Vector3.forward;
tRB = null;
}
}
void Fire()
{
if (!refireTimer.IsRunning)
{
GameObject b = Instantiate(bGO, bulletSpawn.position, bulletSpawn.rotation);
b.transform.position = bulletSpawn.position;
b.transform.rotation = Quaternion.Euler(Vector3.forward) * bulletSpawn.rotation;
refireTimer.Begin();
}
}
public void Update()
{
if (bScript.BulletIsInitialized)
{
if (isTracking)
{
Calculate();
Traverse();
Fire();
}
}
}
}
using UnityEngine;
public class Bullet : Spawnable
{
public float force;
Rigidbody rb;
float maxV, physAcc, acc;
// Use this for initialization
new void Start()
{
base.Start();
rb = GetComponent<Rigidbody>();
maxV = force / rb.mass / rb.drag;
print("Initial maxV= " + maxV + " of object: " + gameObject.name);
}
void Update()
{
acc = maxV - rb.velocity.magnitude;
}
void FixedUpdate()
{
rb.AddRelativeForce(Vector3.forward * force, ForceMode.Acceleration);
physAcc = maxV - rb.velocity.magnitude;
// print("Current velocity=" + rb.velocity + "for object:" + gameObject.name + "acceleration=" + Acceleration + "t=" + Time.realtimeSinceStartup);
}
public float Force
{
get { return force; }
}
public float TopVelocity
{
get { print(name + " has topVelocity=" + maxV); return maxV; }
}
public float FixedAcceleration
{
get
{
return physAcc;
}
}
public float Acceleration
{
get
{
return acc;
}
}
}
using UnityEngine;
/*Most of this class is unused functionality, at least until I get the bullets to collide with proper */
public class Spawnable : MonoBehaviour, IKillable, IDamageable {
Timer life;
public void Spawn(Vector3 position, Vector3 eulerOrientation, float lifespan) //To be called when a Spawnable object needs to exist (DO NOT INSTANTIATE) [Also used by objectpooler much later!!]
{
gameObject.transform.rotation = Quaternion.Euler(eulerOrientation);
gameObject.transform.position = position;
gameObject.SetActive(true);
life.Limit = lifespan;
life.Begin();
}
public float healthpoints, defaultHealth = 1000f;
public virtual void Start()
{
healthpoints = defaultHealth;
life = gameObject.AddComponent<Timer>();
}
public void Kill()
{
gameObject.SetActive(false);
}
public void Damage(float damage)
{
healthpoints -= Mathf.Abs(damage);
if (healthpoints <= 0f)
{
Kill();
}
}
}