0

I have a homing missile script that seems to work 99% of the time, but every so often one of the missiles will start spiralling out of control and not towards the player. I can't see any reason for it, I can't see a reason for the behaviour in the code and I'm after a pair of fresh eye's to take a look and see if I'm missing something obvious. The script below is attached to each missile.

    using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Linq;

    public class missileControl : MonoBehaviour
    {
        public Transform missileTarget;

        public GameObject indicator;

        private int scorePerHit = 1;
        private int scorePerDestroy = 50;
        private int hits = 1;

        [Header("Enemy Culling Variables")]
        [HideInInspector]
        public float distanceToCull = 4f;
        [HideInInspector]
        private Transform spaceShip;

        public Rigidbody missileRigidbody;

        [Header("Missile Control Variables")]
        public float turn = 0.9f;
        private float initialTurn = 0.9f;
        public float missileVelocity = 95f;
        private float initialMissileVelocity = 95f;
        private Vector3 resetMissileVelocity = new Vector3(0f,0f,0f);

        private Transform myTransform;
        private float wiggleMultiplyer = 40f;

        [Header("Firing Audio")]
        public float minPitch = 0.9f;
        public float maxPitch = 1f;
        public AudioClip indicatorClip;
        public TrailRenderer trailRenderer;

        private bool indicatorOff = true;
        private float currentDistance = 100f;
        public float indicatorDist = 300f;


        private IEnumerator delayAimTimer;

        private void Start()
        {
            spaceShip = LevelVariables.currentLevelVariables.spaceShip.transform; // Player to test if behind
            missileTarget = LevelVariables.currentLevelVariables.playerTarget.transform; // Target
            missileRigidbody.velocity = resetMissileVelocity;

            ResetVariables();
        }

        private void OnEnable()
        {
            ResetVariables();
        }

        private void OnDisable()
        {
            missileRigidbody.velocity = resetMissileVelocity;
        }

        void ResetVariables()
        {
            trailRenderer.enabled = false;
            StartCoroutine(DelayTrails());

            indicatorOff = true;

            turn = Random.Range(initialTurn * 0.85f, initialTurn * 1.15f);
            wiggleMultiplyer = Random.Range(0 - (wiggleMultiplyer), wiggleMultiplyer);

            missileRigidbody.velocity = resetMissileVelocity;
            missileVelocity = Random.Range(initialMissileVelocity * 0.85f, initialMissileVelocity * 1.15f);
            missileRigidbody.velocity = transform.forward * missileVelocity;
        }

        IEnumerator DelayTrails()
        {
            yield return new WaitForSeconds(0.15f);
            trailRenderer.Clear();
            trailRenderer.enabled = true;
        }

        private void FixedUpdate()
        {
            if (GameStateController.gameStateController.gameState == GameStateController.GameState.PLAYERSTART)
            {
                if (Vector3.Angle((gameObject.transform.position - spaceShip.position), spaceShip.transform.forward) > 90)
                {
                    if ((gameObject.transform.position - spaceShip.position).sqrMagnitude > distanceToCull * distanceToCull)
                    {
                        KillEnemy();
                        return;
                    }
                }
                else
                {
                    if (indicatorOff)
                    {
                        currentDistance = Vector3.Distance(missileTarget.position, transform.position);
                        if (currentDistance <= indicatorDist)
                        {
                            indicator.SetActive(true);
                            PlayAudioSound(indicatorClip);
                            indicatorOff = false;
                        }
                    }

                    //missileRigidbody.velocity = (transform.forward * missileVelocity) + (transform.right * (Mathf.Sin(Time.time) * wiggleMultiplyer)) + (transform.up * (Mathf.Cos(Time.time) * wiggleMultiplyer));

                    missileRigidbody.velocity = transform.forward * missileVelocity;
                    var rocketTargetRotation = Quaternion.LookRotation(missileTarget.position - transform.position);
                    missileRigidbody.MoveRotation(Quaternion.RotateTowards(transform.rotation, rocketTargetRotation, turn));
                }
            }
            else
            {
                StartCoroutine(DestroyGameObject(gameObject, 0f));
            }          
        }


        void OnCollisionEnter(Collision hit)
        {
            switch (hit.gameObject.tag)
            {
                case "environment":
                    KillEnemy();
                    break;
                case "enemy":
                    KillEnemy();
                    break;
                case "enemyBullet":
                    break;
                case "player":
                    CameraShake.Shake(1f, 0.25f);

                    float deathScale = Random.Range(5f * transform.localScale.x, 10f * transform.localScale.x);
                    GameObject fx = ObjectPooler.currentPool.enemyHits.Spawn();

                    if (fx == null) return;

                    fx.transform.position = transform.position;
                    fx.transform.rotation = Quaternion.identity;
                    fx.transform.parent = hit.transform;
                    fx.transform.localScale = new Vector3(deathScale, deathScale, deathScale);
                    fx.SetActive(true);

                    KillEnemy();
                    break;
                case "playerBullet":
                    ProcessHit();

                    if (hits < 1)
                    {
                        LevelVariables.currentLevelVariables.scoreBoard.ScoreHit(scorePerDestroy);
                        KillEnemy();
                    }
                    break;
            }
        }

        private void ProcessHit()
        {
            LevelVariables.currentLevelVariables.scoreBoard.ScoreHit(scorePerHit);
            hits = hits - 1;
        }

        private void KillEnemy()
        {
            GameObject fx = ObjectPooler.currentPool.enemyDeath.Spawn();

            if (fx == null) return;

            fx.transform.position = transform.position;
            fx.transform.rotation = Quaternion.identity;
            fx.transform.parent = LevelVariables.currentLevelVariables.spawnParent;

            float deathScale = 1f;
            deathScale = Random.Range(1f * transform.localScale.x, 4f * transform.localScale.x);

            fx.transform.localScale = new Vector3(deathScale, deathScale, deathScale);
            fx.SetActive(true);

            StartCoroutine(DestroyGameObject(gameObject, 0f));
        }

        public void PlayAudioSound(AudioClip clip)
        {
            LevelVariables.currentLevelVariables.computerAudioSource.volume = 1f;
            LevelVariables.currentLevelVariables.computerAudioSource.PlayOneShot(clip);
        }

        IEnumerator DestroyGameObject(GameObject turnOffObject, float waitTime)
        {
            yield return new WaitForSeconds(waitTime);
            trailRenderer.Clear();
            trailRenderer.enabled = false;
            turnOffObject.Recycle();
        }

    }

The section below is the code for creating the missile and is part of the enemy weapon firing script.

GameObject missileObj = ObjectPooler.currentPool.destroyerMissileAmmo.Spawn();

                if (missileObj == null) yield break;

                CreateMuzzleFlash(muzzleLocation);

                //LevelVariables.currentLevelVariables.globalMissileAmount = LevelVariables.currentLevelVariables.globalMissileAmount + 1;
                missileObj.transform.localScale = new Vector3(2f, 2f, 2f);
                missileObj.transform.position = muzzleLocation.transform.position;
                missileObj.transform.rotation = muzzleLocation.transform.rotation;

                //missileObj.transform.LookAt(m_target.transform);
                missileObj.SetActive(true);

I don't see any problems with this code that would cause a missile not to head towards the player, does anyone have any idea's

tbr
  • 1
  • 1
  • Are you firing more than one missile at a time? – jdweng Dec 20 '18 at 18:27
  • There are multiple missiles being fired by the enemies at the player. – tbr Dec 21 '18 at 09:35
  • You need to add locks to the code so two missiles don't execute the method at the same time. – jdweng Dec 21 '18 at 09:57
  • Unity physics engine is not the best tool in the world. I don't see anything wrong with your code but pro tip is avoid physics wherever possible. This code could work perfect without rigidbodies and only use physics for hit detection (which is more or less reliable) – Nika Kasradze Dec 21 '18 at 11:11
  • I finally figured it out after eliminating all possibilities.... I found that I wasn't correctly resetting the velocity of the missiles, I had to reset the angular velocity as well as just the velocity. I found that what was causing the problem was when a missile collided with a player the next time that missile was used it would fly off in a spiral, adding an angular velocity reset fixed the issue. – tbr Dec 21 '18 at 14:40

0 Answers0