Unity Scripting: Scripting the Player Controller

The most Learning-full Mine Lander tutorial yet! You’ll set up the level to use collisions, explode the player ship, activate landing pads, and more. To do all this, we’ll be learning a lot of new scripting methods including getting collision info, coroutines, accessing scripts on other objects, spawning new Game Objects- all skills you will need in many other cases, so get to it!

What is covered in this tutorial:

  • - Coroutines
  • - Instantiate new Game Objects
  • - Accessing scripts as a Component
  • - OnCollisionEnter for getting detailed collision info
  • - Swapping materials and colors via script
  • - Destroying a Game Object

Play Lunar Lander:

Lunar Lander<>

Discussion

40 Responses to “Lunar Lander 04: Collisions, Explosions, Landing Pads”
  1. Posts: 35

    Gabriel, another great tut that I enjoyed with my lunchtime coffee. Really do enjoy listening to you and Jonathan Williamson and David Ward – nice relaxed quiet voices.

    A couple of questions.

    In the LandingPad script you leave an “empty” Update function – a function that is called every frame. In a number of other tuts I have watched (on C# mainly) people seem delete it if it is not used. Does it make a difference to delete that? Does it stop being called?

    The other question is about the call to the Activate function from the PlayerController script. First you check for the “LandingPad” tag – which could be more than one object but only one Activate gets triggered so I assume that the line :

    **landingPad = hitInfo.gameObject.GetComponent(“LandingPad”); **

    is somehow making sure that only the script on the object that is being hit is gets called. Not immeadiately obvious, to me at least, what is “hitInfo” – a complete description of the object touched? (Guess I should go and look it up ;-) )

    As always, looking forward to next week.

    gryff :)

    #
    1
    Mar 19, 2012 at 12:49 pm
    • Posts: 268

      Thanks again Gryff :)

      The empty “function Update” should indeed be deleted. It won’t make any noticeable difference to performance, unless you have lots (and I mean LOTS) of instances though. But, always better to keep things as clean and efficient as possible!

      When I’m off my 9-5, I’ll write up a real nice explanation of the Landing Pad bit, in case that was confusing for any others too :)

      #
      1.1
      Mar 19, 2012 at 1:40 pm
      • Posts: 35

        “always better to keep things as **clean and efficient** as possible!”

        And that is one of the major things I’m learning from your tuts ;-) This whole Lunar Landing series has been emphasising that.

        “in case that was confusing for any others too”

        Not so much “confusing” as “what the heck is this hitInfo?”. I did a search on Unity 3D scripting and got 7 results – most seemed to do with raycasting. The only information about “hitInfo’ that was given was:

        “If true is returned, hitInfo will contain more information about where the collider was hit”

        which does not explain much!!

        Look forward to your a more detailed explanation.

        gryff :)

        #
        Mar 19, 2012 at 3:04 pm
  2. I started with Unity3D a few weeks ago. I really like how easy it is. This website is useful to begin with Unity3D.
    I love the video tutorials explaining how to make a complete game from scratch. All tutorials should be well ;)

    #
    2
    Mar 19, 2012 at 3:27 pm
  3. Posts: 34

    Hi I have been realy enjoying this tutorial and seem to have ran into a unusual issue.

    section (32:28) I have the source files :)

    when i open the texture folder and click on the LandingPad there is nothing showing within the inspecter for the tiling options.

    All that shows is the name LandingPad, self-Illumin/Specular and the preview.

    Fortunatly I still have the section 3 files saved in a different location and checked these without the issue.

    I am thinking of exporting the scripts and required features as custom prefabs and simply import them into the numb 3 version.

    Help most welcome

    #
    3
    Mar 19, 2012 at 5:43 pm
  4. Posts: 32

    Hey Gabriel I seem to be havind a problem with the detanators. Whenever I try to explode the ship, or even use a detanator at all,it says null refrence exception.
    Then I clicked on the null refrence exception, and it brought me into the detanator code.
    Can you please see what you can do, if not I’ll just make my own explosions.

    #
    4
    Mar 19, 2012 at 7:24 pm
  5. Posts: 268

    Allright, to further explain the Collision process :) Here’s how the events play out, in general:

    1) A Collider hits another Collider (box, sphere, mesh, etc- doesn’t matter type)
    2) IF at least one of the Colliders is attached to Game Object that also has a Rigidbody, then Unity automatically does the following for EACH Collider:
    a) Get the Game Object that this Collider is parented to
    b) For EACH script on the Game Object, look for “function OnCollisionEnter”
    c) If that function exists in the script, it is executed (ka-choww!)
    3) When OnCollision is called, it also sends a whole ton of info
    4) This info is stored as a “Collision”, it’s just another type, like “Transform”, or “Light”, or “Rigidbody”.
    5) So we use “function OnCollisionEnter (anyName : Collision)” to get this info.
    a) much like declaring a regular variable, see!
    b) ie, “var myVarName : Collision;”
    6) Now, the variable we just created, called “anyName”, contains all that super-useful information about the collision that just happened!

    I hope that helps explain how the whole process goes down let me know if anything else isn’t making sense! Methinks an entire mini-tutorial might be good, just for going over scripting techniques using functions? You’ll use them more than anything else!

    This should also answer the “hitInfo” question, my bad for using a variable name that is also a Unity raycast pre-set variable. It has nothing to do with that at all, it was just a name I came up with that seemed good- sorry for the confusion :P Again that variable can be any name at all (ie, “anyName”, lol).

    Thanks for taking the time to check in with questions! :)

    #
    5
    Mar 19, 2012 at 8:24 pm
    • Posts: 10

      Thanks for the clarification, Gabriel. Makes understanding the process a little easier.

      -OldMan44

      #
      5.1
      Mar 20, 2012 at 12:08 am
    • Posts: 35

      Ahh – me being a little sloppy. I watched the video with my cup of coffee then watched it again – but using the video timeline to get back to the spot that interested me. That spot was where you entered the code that interested me. I failed to notice that you had defined a variable “hitInfo” in the OnCollisionEnter function. So, in your youthful parlance, this old guy is “my bad” ;-)

      And if you need ideas for tutorials – a simple inventory system is my suggestion!! Been trying to do it myself – but lost more hair than my cats ;-)

      And can I put in a plug here for everyone – Daz3D is **giving away** Bryce 7.1 until the end of the month (Mar 2012) – a program that is great for building unique skyboxes (from alien planets to the Cotswold hills) for Unity:

      http://www.daz3d.com/i/shop/itemdetails/?item=11034

      I have a couple of examples in my gallery

      gryff :)

      #
      5.2
      Mar 20, 2012 at 1:31 am
  6. love
    Posts: 2

    cool man

    #
    6
    Mar 20, 2012 at 11:18 am
  7. Posts: 34

    Thank god for moderation, I added a comment re lunar lander part 4.

    Please admin do not post this!!!!

    I am very very new to unity and made a classic error, lets just say i would rather the comment was not posted.

    Somtimes when you create or try to access the shader options it will show only the name of the file, name of shader and the preview.

    you have to click to update the information (too see it all).

    #
    7
    Mar 20, 2012 at 3:34 pm
    • Posts: 268

      You figured it out, so, no reason to be ashamed :) Not that there would be otherwise, lol. And now any others with the same issue, can fix it thanks to your post! And trust me, there are probably others :)

      #
      7.1
      Mar 20, 2012 at 4:20 pm
  8. Posts: 4

    Great series! I can’t wait until the next part. In case anyone is doing it in C# “yield” can not be called directly from the Start() function instead it has to be called through a Coroutine:

    void Start () {
    StartCoroutine(“TestExplosion”);
    }

    IEnumerator TestExplosion() {
    yield return new WaitForSeconds(1);
    Explode();
    }

    #
    8
    Mar 21, 2012 at 1:12 am
  9. Posts: 8

    Hiya,

    Just a quick question regarding communication between scripts;
    You mentioned that there are some shortcut methods that can cause problems on some devices. Is BroadcastMessage() one such potentially problematic “shortcut”? I’m guessing one would consider it a shortcut due to its simplicity.

    Looking forward to seeing you dig into the GUI and jazz. I love how simple setting up a GUI is, and the logic behind it is so effective. Looking into GUIs was one of the first things on my list when I started learning Unity (yeah, I’m THAT guy lol). I thought it’d be complicated, but as I learnt more about it I found it almost too simple! :P

    Rock on big guy! :)

    P.S.
    Nice little game you’ve got cooking. I can’t get past the first level! I’m definitely no “hardcore” gamer! :D

    #
    9
    Mar 24, 2012 at 6:49 pm
    • Posts: 268

      Hi Wetsponge- “BroadcastMessage()” does a whole buncha things to accomplish the end result, whereas if you cache a reference to the script by placing it in a variable, then just call it’s functions or assign variables directly, I believe it’s much, much more efficient.

      Thanks for the compliments, how you enjoy the quick look at GUI in the new tutorial! It’s definitely something I’ll have to make a dedicated tutorial for :)

      #
      9.1
      Mar 30, 2012 at 1:17 pm
  10. Posts: 35

    To Wetsponge:

    It is my understanding that BroadcastMessage() applies only to a parent object and its children. (I used it to flip the door status in the “Logic Maze” example that I posted in “User Submitted Images”)

    Like SendMessage(), that I have also used, both can only pass a single parameter without indulging in some scripting trickery.

    I don’t know about how efficient they are, or how well they operate on different OSs, but the way Gabriel is scripting has opened my eyes to other methods of inter-object communication.

    I too wondered about Gabriel’s about “shortcut methods”. Looking at scripts from all kinds of tutorials blogs etc., very little seems to be mentioned about efficiency, game impact or even OSs. Hope Gabriel continues, and expands, on such issues.

    gryff :)

    #
    10
    Mar 24, 2012 at 11:41 pm
    • Posts: 268

      Gryffydd has it right! From the docs:
      “Calls the method named methodName on every MonoBehaviour in this game object or any of its children.”

      So, that’s another major shortcoming. SendMessage actually works only on scripts on the current object, so is even more limited, and again, it’s doing a lot more work vs just cacheing and directly accessing the script. A little tedious to set up all those connections, but very worth it! :)

      #
      10.1
      Mar 30, 2012 at 1:20 pm
  11. Hello there,

    Thanks for that nice game, even if I still didn’t succeed in landing all the three stations gas. Just a remark, could we add and entry in the options menu to tweak the keys assigns by default for qwerty keyboard? I guess I could change the code to feet my ‘azerty’ keyboard configuration, but I thought it could be great for worldwide distribution purpose.
    And also, how change the ‘Retry’ button to get us immediately into a new playing game? I mean without be forced to click on the ‘ready’ button…

    Anyway, congrats for all your tutorials and for that nice game ;)

    #
    11
    Mar 26, 2012 at 4:47 am
    • Posts: 268

      Thanks Fred! :)

      Input customization can be both simple and tricky- but I agree, it would be very good to have! I’ll add this to my list of future tutorials, it’s definitely something that will be a must-learn, especially when considering worldwide distribution. Thanks!

      #
      11.1
      Mar 30, 2012 at 1:22 pm
  12. Posts: 3

    Hi Gabriel,
    First, great tutorial so far. I am really enjoying it.

    Second, I am having a really strange problem. For some reason the landing pads are not accepting the tag. I set it up in the tag editor and placed it on the prefab. All landing pads are showing it as their tag. But nothing shows up when I land on them. So, I added “print(hitInfo.gameObject.tag);” to the function and when I land on them it says “untagged”. Redid the tagging multiple times and still a no go, I am lost. I googled it as well and no info. Any ideas?

    #
    12
    Mar 27, 2012 at 11:06 pm
  13. Posts: 3

    LOL, my bad. I had put the tag on the mesh and not the collision object :P

    #
    13
    Mar 27, 2012 at 11:33 pm
  14. Posts: 5

    The script to make the landing pad change light color and materials works, however, is there a way I change the landing pad material that’s on my mesh, not the collider?

    My collision mesh and landing mesh are two different objects. Right now the material will change only on the collision.

    Thanks

    #
    14
    May 3, 2012 at 1:43 am
  15. Hi Gabriel,

    Got a problem with the first explosiontest. I’ve put the Explodefunction into the StartFunction and wrote the DestroyFunction. Now Unity throws a NullReferenceException caused by the detonatorscripts. I don’t know what went wrong. My script is the very same as yours!

    #
    15
    Sep 13, 2012 at 8:38 am
    • Posts: 268

      What is the exact nullref? Unity does a good job of pointing you to the source of the error usually. If you double click on the error, where does it lead to? Are you missing some components of the detonator package, perhaps?

      #
      15.1
      Sep 14, 2012 at 12:42 am
      • Thanks for your quick answer!
        In the meantime I’ve figured out that it was my fault: Playing around with my PlayerShip and the first level, I attached the “Main Camera” to the PlayerShip object. Naturally it was destroyed by the Explode-Function too. Everything works fine now.

        Great Series! (And sorry for my stupid question…)

        #
        Sep 14, 2012 at 5:31 am
  16. Posts: 2

    Hey. I am LOVING this tutorial. I have just run into a problem in my code, maybe you could help me locate what is wrong in my code. I’m getting an error telling me I am referencing a script that doesn’t exist. Here are 2 screenshots that might be helpful. The errors show in console at the moment the ship deletes. There is no explosion visual effect when I test run the level.

    http://i.imgur.com/m7Rj9.jpg
    http://i.imgur.com/l8WLH.jpg

    Thanks for you tutorials!

    #
    16
    Nov 20, 2012 at 2:36 am
    • Posts: 268

      Glad you like it! It sounds like you script might be deleting itself, or another, from a GameObject, instead of deleting the GameObject itself. Make sure your destroy call is “Destroy(GameObject)” and not “Destroy(this)”. Let me know if that helps :)

      #
      16.1
      Nov 27, 2012 at 3:18 pm
  17. Posts: 2

    Hi,

    first of all let me say that this series is great!!
    Thanks for teaching us so good :)
    I’m really learning a lot here. I used to use Blender for GE
    but now switched to Unity (still using Blender for modeling tho).

    I’ve got a problem with my landingPad, it is swapping the color to the onColor
    but not the material to the onMaterial… :( Probably some stupid thingy i forgot
    or did wrong but i can’t figure it out. I checked the script for any errors but it is exactly
    the same as yours… Any suggestions are welcome :)

    #
    17
    Feb 2, 2013 at 5:32 am
    • Posts: 2

      ok nevermind the issue was Blender related.
      Apparently, when i exported the file there were 2 materials,
      and i could’nt get rid of them in Unity.
      When i made the landingPad in Blender i created a seperate
      object for the arrows (instead of just texturing them) and then
      combined the landingPad object and the arrows object.
      For some reason Blender exported the new object with 2 materials…

      #
      17.1
      Feb 2, 2013 at 8:34 am
      • Posts: 147

        Unity takes it’s materials not only from the material window, but also on what image is in the UV editor for each face. When you get this problem the quickest solution is to unlink all images from your blend.
        -Alex

        #
        Feb 3, 2013 at 1:47 am
  18. Posts: 10

    Hello!

    Thank you for these excellent tutorials – really enjoying them!

    I’m on the first few minutes of this tutorial testing out the explosion effects. The effect simply doesn’t play and when I view them in the inspector all of the explosions (Detonator-chunks, Ignitor, and mutiExample show this error in the components section: “The associated script can not be loaded. Please fix any compile errors and assign a valid script.” At the top it says “missing (Mono Script)”. I’m a citizen so downloaded the source files so I’m not sure what’s going on here and why. Any ideas anyone?

    Thanks!

    ~Mark

    #
    18
    Mar 20, 2013 at 3:25 pm
    • Posts: 268

      Hi Mike! What version of Unity are you using? I have a feeling, since this tutorial is fairly old now, there might be a compatibility issue going on, another user reported issues with Detonator as well. We might need to update those sources files.

      #
      18.1
      Mar 21, 2013 at 12:24 pm
      • Posts: 10

        I’m using 4.1.0f4 (the latest).

        I had a thought this morning that I’ve been investigating that might be part, if not all, of the problem. When I first started the tutorial, I got the base source files from episode 1. During the next tutorial I realized I was missing something. Thinking I might have deleted something by accident, I got the files again. And everything was there! I must have deleted something then. But then I realized – you’re adding NEW source files with each tutorial step. That’s why I couldn’t find the green texture for the landing pad in my last round.

        So – I copied all of my files and put them into a back up folder, re-downloaded all of the source files, and then one by one put them together into the unity project folder. What do you know – the detonators look correct!

        The only problem is it looks like while all of the pieces are there, there’s still a lot of rework I’ll need to do to get things working correctly. It’s not a full reboot as some of the work is there, and obviously it’ll go faster the 2nd time, but I ~think~ I may have found the problem. I’m going to try and take my lunch break and possibly the wee hours tonight and see if I can get everything back to where I had it, only this time with working explosions! :)

        I’ll let you know what I come up with.

        ~Mark

        PS
        I’d love to see more tutorials on other game types! One suggestion from me would be to remind folks in each episode on when and where they should download the source files if they’re following along using the citizen benefits. :)

        #
        Mar 21, 2013 at 3:00 pm
      • Posts: 10

        Well, I’m a little embarrassed to say that the problem I was having had to do with not understanding how you were distributing source files. I like to follow along typing everything in, leaving my own comments in the scripts so I really got off track once I did a mass update to all of the files. Lesson learned!

        I did run into another problem that seems like it might be a Unity version problem however. I’ve just finished episode 6 and I’ve got everything working with one exception. In the lose function when I use the yield command nothing happens. By nothing I mean no UI appears. My ship still destroys itself, but no UI. If I remove the yield line, everything works 100% correct with the exception of hearing the audio which I’m sure is just being clamped off since there is no delay. Here’s the line I’ve got in the script:

        function Lose()
        {
        yield(WaitForSeconds(3));
        audio.clip = loseClip;
        audio.Play();
        guiMode = “Lose”;
        Time.timeScale = 0;

        loseTexture.enabled = true;
        }

        I’ve tried a number of different formats, looked online for answers, but haven’t found anything.

        Any help would be greatly appreciated!!

        Thanks again for these excellent tutorials!!

        ~Mark

        #
        Mar 24, 2013 at 8:49 pm
  19. Posts: 4

    Hey there, I’m giving this a shot and run into a little problem. When it comes to the OnCollisionEnter function we create, I can not get the else if statement to work properly. The first if statement works fine. Here is the code as it appears in my script.

    function OnCollisionEnter(hitInfo : Collision)
    {
    if(hitInfo.relativeVelocity.magnitude >=2)
    {
    Explode();
    }
    else if (hitInfo.gameObject.tag == “LandingPad”)
    {
    var landingPad : LandingPad;
    landingPad = hitInfo.gameObject.GetComponent(“LandingPad”);
    landingPad.Activate();
    }
    }

    I couldn’t even get the simple print statement to show up in the console when I play it out. It seems as if no matter what code I write under the else if, it wont show any errors, but also wont work as intended. Any brain waves on my issue that might be helpful?

    #
    19
    Mar 30, 2013 at 7:16 pm
    • Posts: 10

      Heya Benjamin,

      I’m still a complete novice, so take my brain waves with that in mind. :)

      Your code looks identical to what I have in mine and mine seems to work fine. The place where I would start to investigate might be on the lander/ship. Is everything set up properly there? Do you have a rigid body set up, for example? Is the Player Controller script attached? Another thing that works for me when I’m trying to figure out a bug is I ask myself what IS working rather than what isn’t and that helps me narrow the areas to search.

      Hope that helps!

      Btw – if/when you get to the yield/wait-for-seconds bit and figure out how to make that work, I’d appreciate some help there. I ~still~ haven’t figured that bit out.

      #
      19.1
      Mar 31, 2013 at 12:08 am
      • Posts: 4

        Hey Mark, thanks for the reply. Ive done some messing around and I think the problem rests in the tag. If I switch around the code so the exlodey part is in the else if statement, it still works, but the landing pad tag part (now the if statement) still doesnt. So that leads me to believe the problem rests with the tags, and not the statements or syntax themselves. So with that narrowing down the problem, you or anyone else have some more insight?

        else if(hitInfo.gameObject.tag == “LandingPad”) //This is the line in question, is there something wrong?

        #
        Mar 31, 2013 at 8:45 am
      • Posts: 4

        Figured it out! I dont know if I did something wonky, or if its because I am using a newer version of Unity, but my Landing Pad objects have the hit box’s attached to them in the hierarchy. So all I had to do was set the tags to the hitbox and all was well!

        #
        Mar 31, 2013 at 7:51 pm
  20. Posts: 1

    Great tutorial Gabriel!

    I just downloaded the video/source for part 4 and inside the zip I found the video from part 3!!!

    If possible could you put the correct video in the download file?

    Thanks :)

    #
    20
    Apr 22, 2013 at 6:19 am

Leave a Comment

You must be logged in to post a comment.