I have implemented an upgrades system in my Unity3d game, and I am pretty sure that I am not doing things in an optimal way. Any advice regarding best practices would be much appreciated.
The idea is that when the player collects a powerup, their run speed and jump speed increases. Collect enough powerups, and you can jump around the level like the incredible hulk.
Play the game here: Super Voxel
The powerup is a basic Sphere object with its Sphere Collider Is Trigger checkbox activated. It has this script attached:
SphereTriggerScript.cs
public class SphereTriggerScript : MonoBehaviour { public GameObject sphereObject; private GameObject playerObject; void Start() { playerObject = GameObject.Find("Player1"); } void OnTriggerEnter (Collider other) { Destroy(sphereObject); PlayerScript script = playerObject.GetComponent<PlayerScript>(); script.jumpForce += 1; script.runSpeed += 1; } } In the scene I have a basic Player1 prefab with this script attached:
PlayerScript.cs
public class PlayerScript : MonoBehaviour { public int runSpeed; public int jumpForce; void Start () { runSpeed = 20; jumpForce = 10; } } The powerup references this script with GameObject.Find. I do understand that this is suboptimal, however the powerups are created programmatically at run time, so it is not possible to simply drag and drop the Player1 game object onto the powerup prefab.
I have modified the default FPSController prefab (specifically the FirstPersonController script) to add a public GameObject field that I populate with the Player1 prefab. Then when I need to get the jump or run speed, I access that script like so:
PlayerScript script = playerObject.GetComponent<PlayerScript>(); m_MoveDir.y = script.jumpForce; Finally, I am doing something a bit funny to position the powerup orbs properly. When creating them, I use a RayCast to position them at the "top" of the building:
int randomNumber = random.Next(0, 100); if (randomNumber > 80) { int maxPossibleHeight = 250; RaycastHit hit; Ray ray = new Ray(new Vector3(x * tileSize, maxPossibleHeight, y * tileSize), Vector3.down); if (tileObject.GetComponentInChildren<MeshCollider>().Raycast(ray, out hit, 2.0f * maxPossibleHeight)) { int randomHeightOffset = random.Next(2, 12); float height = hit.point.y; GameObject powerup = (GameObject)GameObject.Instantiate (Resources.Load (powerupPrefabName)); powerup.transform.position = new Vector3(x * tileSize, height + randomHeightOffset, y * tileSize); } }
Screen.lockCursor = trueto lock the cursor. It's a little easier to play when the cursor is locked. \$\endgroup\$Cursor.lockState = CursorLockMode.Locked;Cursor.visible = false;\$\endgroup\$