Ack, the insanity! Heh…
-
Find is slow so don’t use it unless you have to and even then, do it somewhere where you can cache the result as few times as possible. I have never needed to use Find though. Use a class Variable for drag and drop from the inspector if you can.
-
whenever you get or find something, always check to see if the result was null. If these functions fail for any reason, you’ll get null, and therefore null errors. Check for null and print a nice Debug.logError() for yourself.
-
don’t use the ‘as’ keyword, When no generic is available, cast with round brackets: (MyType)MyFunction();
-
Check out PoolManager. It will save you from a lot of performance issues doing massive amounts of instanciation work. This isn’t just a plug, we do a lot of this in our game, that is why we made it. We have support forums as well and are always happy to help. We are releasing a major new version by tomorrow night PST if everything goes well, including a new website and more docs with code examples.
WARNING: I did NOT test this. I just reformatted it in a way that I think makes for a more understandable approach. I am only posting it as an example. I hope this helps:
public class PlayerControl : MonoBehaviour
{
public int moveSpeed;
public GameObject bulletPrefab;
public Transform bulletSpawnPoint;
private CharacterController controller;
private GameObject bulletGO;
// Use this for initialization
void Awake()
{
// Cache
this.controller = GetComponent<CharacterController>();
if (this.controller == null)
Debug.LogError("Character constroller not found.");
}
// Update is called once per frame
void Update()
{
PlayerMove();
FireWeapons();
}
private void PlayerMove()
{
if (this.controller)
{
float x = Input.GetAxis("Vertical");
float y = Input.GetAxis("Horizontal") * -1;
var moveDir = new Vector3(x, 0, y);
// There should be a more direct way to do this, but if it works....
moveDir = transform.TransformDirection(moveDir) * moveSpeed;
controller.Move(moveDir * Time.deltaTime);
}
}
private void FireWeapons()
{
if (Input.GetButton("Fire1"))
{
// Using 'var' because this is obviosuly a GameObject
var bulletGO = (GameObject)Instantiate(bulletPrefab,
bulletSpawnPoint.position,
Quaternion.identity);
// Make it move here....
}
}
This is a major aside, but… I recommend NOT using underscores before private variables. Coming from Python it pains me to admit this, but there is a cool little trick in Unity and an important concept in C# that supersedes this.
First, in C# it is common to use an underscore for a “backing field” which is just a private variable that is used by a property or class to hold some information while an interface is provided for public use. For example, here is a way to make a variable read-only from outside a class, but setable from inside:
private float _speed;
public float speed
{
get
{
Debug.Log("returning speed");
return _speed;
}
}
In Unity, you can use an underscore in front of a public variable and it will still show up in the inspector, but without the underscore. This means you can have a public backing field! This is an awesome little workaround. For example, say you wanted the variable in the example to be settable in the inspector, but only read-onyl from code with extra stuff.
public float _speed;
public float speed
{
get
{
Debug.Log("returning speed");
return _speed;
}
}
Notice the only difference is I made it public. This isn’t as clean as we would like, design wise, but unless Unity starts supporting properties in the inspector, which wouldn’t be easy without a custom editor, it still works pretty great.