I've been toying around with Unity 5 lately, and in an effort to start making an actual game, I've built a ball controller similar to the one found in the Unity tutorial Roll-a-ball.
In essence, the player controls a small ball that rolls around a "level". The ball can accelerate at a rate in the range \$1\rightarrow10\$ depending on what I (the designer) choose. The controller also manually calculates drag to create a "low-gravity" feel, but still have a sense of speed. Drag is calculated using the following formula:
$$\text{drag}=\frac{\text{acceleration vector magnitude}}{\text{some dividend}}$$
I'm wondering about the following things:
- Is it appropriate for the controller to do things such as drag calculation, or should this be separated into a separate area?
- I'm currently using a dictionary, looping through it, checking for keypresses, and then applying force if a key is pressed. Is this a good way to handle it? Will this ever slow anything down?
- Are there any performance improvements that can be made?
- Anything else?
BallController.cs
using UnityEngine;
using System.Collections.Generic;
/// <summary>
/// This class contains various methods and attributes
/// used to control the "vehicle".
/// </summary>
[System.Serializable]
[RequireComponent(typeof(Rigidbody))]
public class MoveVehicle : MonoBehaviour
{
/// <summary>
/// The force of an acceleration. This will be applied
/// to the ball when it's accelerating.
/// </summary>
[Range(1, 10)]
public float accelerationForce;
/// <summary>
/// This determines the drag being exerted on the ball
/// as it moves. Drag is determined through the formula
/// drag = accelerationForce / dragDividend
/// </summary>
[Range(0, 1000)]
public float dragDividend;
private Rigidbody rigidBody;
private Dictionary<KeyCode, Vector3> keyMappings = new Dictionary<KeyCode, Vector3>() {
{KeyCode.Space, new Vector3(0, 5.5f, 0)},
{KeyCode.W, new Vector3(0, 0, 1)},
{KeyCode.A, new Vector3(-1, 0, 0)},
{KeyCode.S, new Vector3(0, 0, -1)},
{KeyCode.D, new Vector3(1, 0, 0)},
{KeyCode.UpArrow, new Vector3(0, 0, 1)},
{KeyCode.LeftArrow, new Vector3(-1, 0, 0)},
{KeyCode.DownArrow, new Vector3(0, 0, -1)},
{KeyCode.RightArrow, new Vector3(1, 0, 0)}
};
/// <summary>
/// Check if the ball is near to, or touching the
/// ground. This is used to determine whether the
/// vehicle can move or not.
/// </summary>
public bool IsGrounded()
{ return Physics.Raycast(this.transform.position, -Vector3.up, 0.65f); }
/// <summary>
/// Initialize things like our Rigidbody component,
/// or other things that can only be initialized in
/// Start.
/// </summary>
public void Start()
{ this.rigidBody = GetComponent<Rigidbody>(); }
/// <summary>
/// Apply thrust to the ball. The faster the vehicle
/// gets, the more drag we apply to the rigidbody. This will
/// create the effect of reaching a "maximum" speed.
/// </summary>
public void FixedUpdate()
{
foreach(KeyValuePair<KeyCode, Vector3> keyMapping in this.keyMappings)
{
if(Input.GetKey(keyMapping.Key) && this.IsGrounded())
{
Vector3 objectForce = keyMapping.Value * this.accelerationForce;
this.rigidBody.drag = objectForce.sqrMagnitude / this.dragDividend;
this.rigidBody.AddForce(objectForce);
}
}
}
}