As seems to be the case with many new Unity folks, I opted to try and make a 2D space shooter as my first game. Between following along with numerous tutorials like Tanks! and logging my own time tinkering in Unity with research and trial/error, I have (maybe) a grand total of 90 hours of experience - so please forgive any common errors I may make. I do welcome constructive criticism. I know my code is heavily commented and that’s a “beginner sin” - but there’s a very good reason beginners do it.
Of those 90 hours, I’ve probably I’ve been struggling to get my ship movement working for 8 of them. Originally I had the ship moving by just changing the position of the transform, but the more I played with that in testing, the less natural it felt. I wanted some heft and weight to movement. Enter ApplyForce and a change to using physics. It took about 8 hours of research and more tutorials to get 95% of my movement the way I wanted it. It feels good now - but…
The remaining 5% is getting the ship to strafe left and right slowly and smoothly while remaining aligned with where the mouse pointer is - so you can, in effect, circle-strafe an enemy easily. I’ve hammered lots of solutions into that slot, but none have done what I was trying to accomplish. I’ve included a number of failed experimental circle-strafe attempts as comments. I did not keep all of their random variables in the code as I didn’t want to confuse it with a dozen useless elements, but each was “functional” when I tested it. I’m hoping someone can assist with this as I feel like I’m really close, but just can’t find the last nudge.
using UnityEngine;
using System.Collections;
public class Space2DStrafeMove : MonoBehaviour
{
//movement variables
public float v_speed = 3;
public float v_rotationSpeed = 0.25f;
//private calculation variables
private Vector3 v_lookDirection;
private float v_lookAngle;
//object variables
private Rigidbody2D v_rigidBody2D;
// Use this for initialization
void Start()
{
//store a reference to the attached Rigidbody2D object
v_rigidBody2D = GetComponent<Rigidbody2D> ();
}
//FixedUpdate is called at a fixed interval and is independent of frame rate. Put physics code here.
void FixedUpdate()
{
//Store the current horizontal input in the float moveHorizontal.
float v_moveHorizontal = Input.GetAxis ("Horizontal");
//Store the current vertical input in the float moveVertical.
float v_moveVertical = Input.GetAxis ("Vertical");
//strafe toggle, ship remains oriented towards mouse cursor
if (Input.GetKey(KeyCode.LeftShift))
{
//Establish the mouse position in the camera relative to the position of the ship
v_lookDirection = Camera.main.ScreenToWorldPoint(Input.mousePosition) - transform.position;
//Create an angle that the ship will need to move towards in order to look at the mouse cursor
v_lookAngle = Mathf.Atan2(v_lookDirection.y, v_lookDirection.x) * Mathf.Rad2Deg;
//Use the two store floats to create a new Vector2 variable movement.
Vector2 v_movement = new Vector2 (v_moveHorizontal, v_moveVertical);
//Call the AddForce function of our Rigidbody2D rb2d supplying movement multiplied by speed to move our player.
v_rigidBody2D.AddRelativeForce(v_movement * v_speed);
//Rotate the ship towards the established angle, -90f to account for ship alignment, over time
//Rotates instantly, not desirable
transform.rotation = Quaternion.Euler(0f, 0f, v_lookAngle - 90f);
//turns the ship as fast as I move the cursor, and in the right direction
//transform.rotation = Quaternion.AngleAxis(v_lookAngle-90, Vector3.forward);
//instantly snaps the ship "up"
//transform.rotation = Quaternion.Euler(0f, 0f, v_lookAngle - 90f * Time.fixedDeltaTime) ;
//instantly snaps the ship "up"
//transform.rotation = Quaternion.Euler(0f, v_lookAngle - 90f * v_rotationSpeed * Time.deltaTime, 0f);
//undesirable result
//transform.eulerAngles = Vector3(0, v_lookAngle, 0);
//undesirable result
//transform.rotation = Quaternion.Slerp(v_lookAngle, v_lookDirection.y, Time.time - startTime);
//undesirable result
//transform.rotation = Quaternion.RotateTowards(transform.rotation, v_lookDirection, Time.deltaTime * 10f);
//smooth rotation to the Z axis (flips the ship over)
//transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(v_lookDirection - transform.position), v_rotationSpeed * Time.deltaTime);
//undesirable result
//transform.rotation = Quaternion.AngleAxis(v_lookAngle, Vector3.forward);
//ship spins smoothly over onto it's back
//transform.rotation = Quaternion.Slerp(this.transform.rotation, rotationA, Time.deltaTime * speed);
}
//this creates smooth up and down, rotate left and right, fly in direction the transform is pointing
if (!Input.GetKey(KeyCode.LeftShift))
{
//Use the two store floats to create a new Vector2 variable movement.
Vector2 v_movement = new Vector2(0, v_moveVertical);
//rotate the transform on the horizontal axis
transform.Rotate(0, 0, -v_moveHorizontal);
//apply force relative to the existing heading of the ship
v_rigidBody2D.AddRelativeForce(v_movement * v_speed);
}
}
}