vrijdag 30 januari 2015

Firing 2D Projectiles in Unity3D with C#

If you have ever tried to make a 2D projectile in Unity, you may have encountered a problem. You want the projectile to face its target, right? Well, that isn't as simple as it would seem, as there isn't a look-at function for 2D game objects. Not yet at least, I've come across posts claiming the developers at Unity were working to implement that function.

But I don't want to wait, that's why I made one myself.


At first, I just used the regular Look-at function and added another sprite on top of the projectile with a Y rotation of 90. It works, it's simple, but it's kind of hack-y and ugly.

This script should be put on the projectile.

ProjectileBehaviour.cs:
using UnityEngine;
using System.Collections;

public class ProjectileBehaviour : MonoBehaviour 
{
 public Vector3 targetPos;
 public GameObject projectileOwner;

 [SerializeField] private float speed;
[SerializeField] private AudioClip sound;

 // Use this for initialization
 void Start () 
 {
  transform.LookAt(targetPos); //Look at the target position passed down from the firing game-object
 }
 
 // Update is called once per frame
 void FixedUpdate () 
 {
  transform.Translate(Vector3.forward*Time.deltaTime*speed); //Move towards the target position
 }

 void OnCollisionEnter2D (Collision2D collision)
 {
  if (collision.gameObject != projectileOwner) //These are just examples of what you can do for collision-detection
  {
   if (collision.gameObject.tag == "Solid")
   {

   }
   else 
   {
    if (collision.gameObject.tag == "Player")
    {
     collision.gameObject.GetComponent().health -= 1;
    }
    else
    {
     collision.gameObject.GetComponent().health -= 1;
    }
   }

   Destroy(gameObject); //Destroy self on-hit
  }
 }
}

If you want the player to be able to point and click at any location to shoot, you'll need to translate the screen-point to an in-game position. This can be done with the following function inserted into the firing script.

void CursorAdjustment ()
{
 float distance = transform.position.z - Camera.main.transform.position.z; //Here the Z axis is defined
 targetPos = new Vector3(Input.mousePosition.x, Input.mousePosition.y, distance); //The on-screen location is stored within targetPos
 targetPos = Camera.main.ScreenToWorldPoint(targetPos); //The location in-game is calculated
}

The way I found to create my own 2D LookAt is with the following lines of code.

Quaternion rotation = Quaternion.LookRotation
 (targetPos - transform.position, transform.TransformDirection(Vector3.up)); //This is basically how a LookAt works, but turn the Y rotation a little bit to make it face the screen
 transform.rotation = new Quaternion(0, 0, rotation.z, rotation.w);

Now just make sure that the projectile is instantiated with this rotation and it'll work as intended.

Geen opmerkingen:

Een reactie posten