teaching machines

HNRS 304.503 Lecture 17 – Escaping from the island, keeping things visible, sound effects

November 16, 2012 by . Filed under fall 2012, honors 304.503, lectures.

Agenda

Player with jump control

We want to be able to turn our player’s jump ability on and off. That can be done through the First Person Controller’s Character Motor script component. Let’s simplify the process a bit with our own PlayerController component that wraps around the relevant operations:

public void EnableJumping(bool isEnabled) {
  GetComponent<CharacterMotor>().jumping.enabled = isEnabled;
}

public bool CanJump() {
  return GetComponent<CharacterMotor>().jumping.enabled;
}

Meet boat

We want a boat that we may or may not be able to jump into. If the player cannot jump, let’s pop up a message letting them know they’re destined to perish on the island.

  1. Place boat.
  2. Add an empty on the shore near the boat.
  3. Give it a sphere collider.
  4. Make collider a trigger.
  5. Add a script:
    private bool isNearBoat;
    private PlayerController player;
    public GUISkin skin;
    
    void Start() {
      player = GameObject.Find("Player").GetComponent<PlayerController>();
    }
    
    void OnGUI() {
      if (isNearBoat && !player.CanJump()) {
        GUI.Box(new Rect(10, Screen.height - 70, Screen.width - 20, 60), "You're too heavy laden to board the boat.", skin.box);
      }
    }
    
    void OnTriggerEnter(Collider collider) {
      isNearBoat = true;
    }
    
    void OnTriggerExit(Collider collider) {
      isNearBoat = false;
    }
  6. Add GUI Skin in project panel.
  7. Increase box font size.
  8. Add script to empty.

Flip-up coins

We want the coins to dazzle up when we run into one.

  1. Make a coin prefab, an empty with the model as a child.
  2. Add a collider to the empty.
  3. Make the collider a trigger.
  4. Add a script to play the animation. Do we attach it to the parent or child? The parent. It’s easier to swap the child out with a different model that way.
    void OnTriggerEnter(Collider collider) {
      coin.animation.Play("dissipate");
      Destroy(gameObject, 2.0f);
    }
  5. We need access to the child coin to get at the animation!
    private Transform coin;
    void Start() {
      coin = transform.Find("greedee_coin");
    }
  6. Don’t play animation if already playing.

Sound

Let’s play a sound on collect.

  1. Add an Audio Source component to the coin prefab.
  2. Generate a collect sound (sfxr).
  3. Import audio file.
  4. Set audio file as Audio Source’s audio clip.
  5. Play in a script with:
    audio.Play();

Disable jumping

We want to stop the player from jumping on a coin collect.

  1. Register player in CoinKiller.Start.
  2. Disable jumping in OnTriggerEnter.

Keeping coins visible

Once a coin is collected, we want it to raise up in front of the player, always visible. That’s gratifying.

  1. Try transforming it in Update to in front of the player.
  2. Be disappointed.
  3. Add a new layer named Overlay.
  4. Add a second camera whose Culling Mask includes only Overlay, whose Depth is 1, and whose Clear Flags is Depth only.
  5. Make it a child of the main camera. Switch to ortho, size 5 (a magic number).
  6. Make the main camera Culling Mask not include Overlay.
  7. On coin hit, change the layer of the coin and all it’s children:
    SetLayer(coin.gameObject, 8);
    
    static void SetLayer(GameObject gameObject,
                         int layer) {
      gameObject.layer = layer;
      foreach (Transform child in gameObject.transform) {
        SetLayer(child.gameObject, layer);
      }
    }
  8. In Update, position the coin in front of the camera (all magic numbers):
    void Update() {
      if (isHit) {
        transform.position = player.transform.position + player.transform.forward * 3.0f + 8.0f * player.transform.right + -3.0f * player.transform.up;
      }
    }

Haiku