1
\$\begingroup\$

I'm currently creating a scrip that handles the projectile movement and it's almost where I want it to be. Currently the script correctly instantiates the projectiles, moves the projectiles towards the mouse and deletes them off screen, but the speed of the projectile is not constant (faster or slower depending on how close the mouse is to the player) and after the projectile is fired, it follows the position of the mouse until it flies off screen.

public class LetterController : MonoBehaviour {
    private List<GameObject> letters = new List<GameObject>();
    public GameObject letterPrefab;
    public float letterVelocity;
    Vector3 direction;
    void Update()
    {
        direction = Input.mousePosition;
        direction.z = 0.0f;
        direction = Camera.main.ScreenToWorldPoint(direction);
        direction = direction - transform.position;
        if (Input.GetMouseButtonDown(0))
        {
            GameObject letter = (GameObject)Instantiate(letterPrefab, transform.position,Quaternion.identity);
            letters.Add(letter);
        }
        for (int i = 0; i < letters.Count; i++)
        {
            GameObject goLetter = letters[i];
            if (goLetter != null)
            {
                goLetter.transform.Translate(direction * Time.deltaTime * letterVelocity);
                Vector3 letterScreenPosition = Camera.main.WorldToScreenPoint(goLetter.transform.position);
                if (letterScreenPosition.y >= Screen.height || letterScreenPosition.y <= 0 || letterScreenPosition.x >= Screen.width - 20 || letterScreenPosition.x <= -20)
                {
                    DestroyObject(goLetter);
                    letters.Remove(goLetter);
                }
             }
          }
       }
   }

I tried moving everything from Update() into a separate function called Shoot() and called that from Update(). I tried putting Vector3 direction in its own Vector3 function and calling it in goLetter.transform.Translate. I also tried using LateUpdate(). Nothing I've tired has made any significant changes to how the projectile interacts in Unity. I'd like to have the projectiles move at a constant speed and not follow the cursor but rather travel in a straight line anyone got any clues?

\$\endgroup\$

1 Answer 1

3
\$\begingroup\$

Your problem here is two fold:

First, when you spawn an object, that should be the last the current script interacts with it. From that point forward, the new object should control its own behavior. You need to modify your projectile to handle its own movement.

The second is the use of Vector2.MoveTowards() instead of Translate().

For projectiles that don't track the mouse, like a bullet:

using UnityEngine;
using System.Collections;

public class FixedProjectile : MonoBehaviour {
    public Transform target;
    public float speed=6.0f;

    void OnStart()
    {
        target=Camera.main.ScreenToWorldPoint(Input.mousePosition);
    }

    void Update() {
        float step = speed * Time.deltaTime;
        transform.position =Vector2.MoveTowards(transform.position,target.position,step);
    }
}

For projectiles that track the mouse, like a guided missile:

using UnityEngine;
using System.Collections;

public class MouseGuidedProjectile : MonoBehaviour {
    public Transform target;
    public float speed=6.0f;

    void Update() {
        target=Camera.main.ScreenToWorldPoint(Input.mousePosition);
        float step = speed * Time.deltaTime;
        transform.position =Vector2.MoveTowards(transform.position,target.position,step);
    }
}

For projectiles that track a specific target, like a guided missile with target lock, simply remove the target line from Update() :

using UnityEngine;
using System.Collections;

public class GuidedProjectile : MonoBehaviour {
    public Transform target;
    public float speed=6.0f;

    void Update() {
        if(target!=null)
        {
            float step = speed * Time.deltaTime;
            transform.position =Vector2.MoveTowards(transform.position,target.position,step);
        }
    }
}

and set the target transform after you instantiate the object

GameObject missile = (GameObject)Instantiate(prefab, transform.position,Quaternion.identity);
missile.target=GameObjectToTarget.transform;
\$\endgroup\$
7
  • 1
    \$\begingroup\$ In your ScreenToWorldPoint examples, it looks like target should be of type Vector2 instead of Transform. \$\endgroup\$
    – DMGregory
    Dec 3, 2017 at 18:59
  • \$\begingroup\$ You're right. I'll update when I get back to a computer. Code formatting is terrible on mobile \$\endgroup\$
    – Stephan
    Dec 3, 2017 at 19:02
  • 2
    \$\begingroup\$ I applaud you for writing this on mobile. People like you who are so keen to help even through the horribleness that is mobile, is what keeps this community (and the world) moving forward. Thank you. \$\endgroup\$
    – DCON
    Dec 3, 2017 at 19:09
  • 1
    \$\begingroup\$ Note that First, when you spawn an object, that should be the last the current script interacts with it isn't necessarily true: there's an overhead on scripts having their own Update() methods. Having a central script that runs Update() and tells other objects to perform frame-tick-code is more efficient. But correctly organizing your software architecting to use that design pattern is too long for a comment. \$\endgroup\$ Dec 3, 2017 at 20:46
  • 1
    \$\begingroup\$ I had been so confused for while. This really helped. Thanks! \$\endgroup\$ Dec 3, 2017 at 21:25

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .