The walls finally work! For a while I could make the player stay upright and have it walk through walls, or I could have it bounce off the walls, but I couldn't make it just stop. However, it turns out that increasing the drag coefficient keeps the avatar from skidding away from the wall, and increasing the avatar's mass keeps it from flying off into space when it hits another object.
I also made some progress on parenting. In Unity, one object can be set as the "parent" of another, meaning that moving the parent object will move all the children as well. In Abandon, the player has to find and pick up a halo before exiting the level. I had already learned how to make one object the parent of another from the video tutorials, but I couldn't figure out how to do it from a script.
It turns out that you're not supposed to directly make one object the parent of another; you're supposed to make the transform of one object the parent of the transform of the other object. So the code looks something like this:
Transform t = other.transform;
t.parent = transform;
Along the way, I found another useful function: OnTriggerEnter. If I check isTrigger in the collider for the halo, then when another object collides with it, both of them will run the OnTriggerEnter function (if they have one). This saved me the bother of having to write a script to figure out if the player and halo are in the same position; Unity does it for me.
It does seem like pretty much every function I want to use is already built into Unity somewhere. The hard part is finding out how to do it! Which brings me back to keyboard input.
In my last entry, I discussed using events and the OnGUI function to process keyboard input. That was fine as far as it went, but when I read Caryn's last entry, in which she mentioned that her avatar couldn't move diagonally, I realized that I had the same problem. Since the only way I knew how to handle keyboard input was with OnGUI, and OnGUI runs when an event occurs (such as a key press), the program could only deal with one key at a time. First I tried to rectify this by storing a "move" vector as an instance variable, adjusting it according to keyboard input, and running the actual movement in the Update function, but that didn't help. Then I tried handling KeyUp and KeyDown events separately, but it didn't work because holding down a key creates a series of KeyDown events, so the avatar moved faster and faster but didn't stop because there were so many more KeyDowns than KeyUps.
I keep having the same recurring problems with the Unity documentation: it's hard to find the function you want, when you do find it it's not always clear how to use it, and while there are a few cross-references on each page, most pages don't link to all the other pages that it would be useful to know existed. It's the third issue that came into play here: if the documentation had more cross-references, it wouldn't have taken me nearly so long to find Unity's other methods of handling keyboard input. The Input class's function GetKey(KeyCode key), for example, returns a boolean stating whether the specified key is being pressed right now. Once I knew it existed, I used GetKey to check the arrow keys and made the Update function create a new movement vector every frame, based on which key(s) were pressed. Not only did it work for both straight and diagonal movement, the motion was smoother than before. Here's the final code from Update():
Vector3 move = Vector3.zero;
if (Input.GetKey(KeyCode.UpArrow))
move = move+Vector3.forward;
if (Input.GetKey(KeyCode.DownArrow))
move = move-Vector3.forward;
if (Input.GetKey(KeyCode.RightArrow))
move = move+Vector3.right;
if (Input.GetKey(KeyCode.LeftArrow))
move = move-Vector3.right;
move.Normalize();
transform.Translate(move*Time.deltaTime*speed);