Search Unity

Official Roll-a-ball Tutorial Q&A

Discussion in 'Community Learning & Teaching' started by Adam-Buckner, Apr 17, 2015.

  1. OneAsterisk

    OneAsterisk

    Joined:
    Aug 2, 2016
    Posts:
    5
    I actually found out why, I didnt have ;
     
  2. ladyonthemoon

    ladyonthemoon

    Joined:
    Jun 29, 2015
    Posts:
    236
    Please, post your script using the proper tags, like @OboShape asked you to do.
     
  3. Ynavoig

    Ynavoig

    Joined:
    Jul 29, 2016
    Posts:
    3
    Hi, i'm trying to complete the part two (Moving the player) of the tutorial but I'm getting the following error at line 6: "Field 'PlayerController.rb' is never assigned to, and will always have its default value null".

    And this is the error that appears in the console when I try to play the game:
    NullReferenceException: Object reference not set to an instance of an object
    PlayerController.FixedUpdate () (at Assets/Scripts/PlayerController.cs:19)

    Could someone help me?

    Code:
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class PlayerController : MonoBehaviour {
    5.  
    6.     private Rigidbody rb;
    7.  
    8.     void Start () {
    9.         rb.GetComponent <Rigidbody> ();
    10.     }
    11.  
    12.     void FixedUpdate () {
    13.      
    14.         float moveHorizontal = Input.GetAxis ("Horizontal");
    15.         float moveVertical = Input.GetAxis ("Vertical");
    16.  
    17.         Vector3 movement = new Vector3 (moveHorizontal, 0.0f, moveVertical);
    18.  
    19.         rb.AddForce (movement);
    20.     }
    21. }
     
    Last edited: Aug 3, 2016
  4. WingedOne

    WingedOne

    Joined:
    Jul 27, 2016
    Posts:
    7
    Do you have rigid body physics component added to the ball? Is this script on the ball as a component?
     
  5. Ynavoig

    Ynavoig

    Joined:
    Jul 29, 2016
    Posts:
    3
    Yes, and yes.
     
  6. OboShape

    OboShape

    Joined:
    Feb 17, 2014
    Posts:
    836
    Evening,

    looking at your Start() method, you currently have
    Code (CSharp):
    1.  void Start () {
    2.         rb.GetComponent <Rigidbody> ();
    3.     }
    But, rb is a variable that needs assigned to before it can be used, so we need to assign 'rb' with the Rigidbody component, by changing that line in Start() to the following.
    Code (CSharp):
    1.  void Start () {
    2.         rb = GetComponent <Rigidbody> ();
    3.     }
     
  7. Ynavoig

    Ynavoig

    Joined:
    Jul 29, 2016
    Posts:
    3
    Oh, what a slack of attention, realy sorry for that. And thanks a lot.
     
  8. OneAsterisk

    OneAsterisk

    Joined:
    Aug 2, 2016
    Posts:
    5
    Umm, I did if you didnt notice. I made another post with it.
     
  9. OboShape

    OboShape

    Joined:
    Feb 17, 2014
    Posts:
    836
    It's all good . Part of the learning curve
     
  10. ladyonthemoon

    ladyonthemoon

    Joined:
    Jun 29, 2015
    Posts:
    236
    You are a saint... :)
     
  11. Beyond-Ken

    Beyond-Ken

    Joined:
    Dec 19, 2012
    Posts:
    7
    This game as written works with a wired XBox controller and Windows 10.

    The code:

    float moveHorizontal = Input.GetAxis("Horizontal");
    float moveVertical = Input.GetAxis("Vertical");

    gets the values of the left thumb joystick.

    Does anyone know the code for the left trigger?
     
  12. OboShape

    OboShape

    Joined:
    Feb 17, 2014
    Posts:
    836
    if you have a look here
    http://wiki.etc.cmu.edu/unity3d/index.php/Joystick/Controller

    you may have to add another input to the input manager for the controller button 4.

    Im not 100% sure if Matt covered it, but theres certainly alot of info about the input manager here in his Couch wars live training session
    http://unity3d.com/learn/tutorials/projects/mini-projects/couch-wars-local-multiplayer-basics
     
  13. Genero

    Genero

    Joined:
    Nov 14, 2012
    Posts:
    9
    Everything works but I'm a little curious about something you did in the tutorial with the text object, that I hope is possible to do differently. My problem is with video 7 of 8 right around the 7:53 mark where you drag the text object into the text property of the PlayerController script. I'd much prefer it if this could be done in the code instead, so that if an error occurs in the future, it will be much easier to have everything as centralized within the code as possible.

    EDIT: Oh yeah, here's a link to the video with a timestamp, to make things a little easier:


    To illustrate, I did something similar to what I want to do now, when I fetched the RigidBody component for reference in the PlayerController script:

    rb = GetComponent<Rigidbody>();

    I assume this works because the script is on the Player object and that the RigidBody component can then be found through that connection. However, in this case the countText object is not directly associated with the Player object and I'm therefore looking for a way to establish this reference from within the PlayerController script.

    Thanks in advance!
    - Dave
     
  14. isra2002

    isra2002

    Joined:
    Aug 7, 2016
    Posts:
    2
    I have do teh movig player tutorial exactly like the video and i have the movement speed set to 100 but my ball doesn't move
    Please help
     
  15. OboShape

    OboShape

    Joined:
    Feb 17, 2014
    Posts:
    836

    Yep its totally possible, but firstly you will have to find the reference, so either create a tag for the 'Count Text' child on the canvas and find object, then use GetComponent<Text>() on that.
    or
    find the gameobject name and then use the GetComponent<Text>() on it.

    there is a thread with some info on it that may help
    http://forum.unity3d.com/threads/cant-gameobject-find-on-ui-text.293008/

    also have a look at the different ways to use Find by either name, tag or type here that may give some more info.
    https://docs.unity3d.com/ScriptReference/GameObject.html
     
  16. OboShape

    OboShape

    Joined:
    Feb 17, 2014
    Posts:
    836
    have you had a look through this thread as there are a few things that you could check as a few times it has came up.

    is the playercontroller script attached to the player?
    Have you capitalised your methods ie Start() not start() and FixedUpdate() not fixedupdate()/
    Is there a rigidbody component?
    Have you checked that 'IsKinematic' is unticked within the rigidbody of the player ball?

    if its none of those, can you post a pic of your inspector for the player and the PlayerController script please so we can have a better look.
     
  17. Urasam

    Urasam

    Joined:
    Aug 2, 2016
    Posts:
    2
    Thank you for the answer. The issue was another one and I found the solution in the comment section of the 8th video from the tutorial series. The thing is that you have to tag the empty pick up parent object (which stores all pick ups) with "Pick Up", too. This was not mentioned in the videos and now it works, after I changed it.
     
  18. Sw00d

    Sw00d

    Joined:
    Aug 8, 2016
    Posts:
    2
    my only problem is that i don't have a skybox or a directional light as a default. how do i do?

    looks like this
    upload_2016-8-8_16-14-2.png
     
  19. andyace

    andyace

    Joined:
    Aug 9, 2016
    Posts:
    4
    Hi all,
    I am having difficulty getting the score to display, I keep getting this error:

    NullReferenceException: Object reference not set to an instance of an object
    PlayerController.setCountText () (at Assets/Scripts/PlayerController.cs:47)

    here is my code:
    any help would be greatly appreciated!!
    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using UnityEngine.UI;
    4. using System.Collections;
    5.  
    6. public class PlayerController : MonoBehaviour
    7. {
    8.     //gameCode
    9.  
    10.     public float speed;
    11.     public Text countText;
    12.  
    13.     private Rigidbody rb;
    14.     private int count;
    15.  
    16.     void Start()
    17.     {
    18.         rb = GetComponent<Rigidbody>();
    19.         count = 0;
    20.         setCountText();
    21.     }
    22.  
    23.     //physics code
    24.     void FixedUpdate()
    25.     {
    26.         float moveHorizontal = Input.GetAxis("Horizontal");
    27.         float moveVertical = Input.GetAxis("Vertical");
    28.         Vector3 movement = new Vector3(moveHorizontal, 0.0f, moveVertical);
    29.         rb.AddForce(movement * speed);
    30.  
    31.  
    32.     }
    33.     void OnTriggerEnter(Collider other)
    34.     {
    35.         if (other.gameObject.CompareTag("Pick Up"))
    36.         {
    37.             other.gameObject.SetActive(false);
    38.             count = count + 1;
    39.             setCountText();
    40.  
    41.  
    42.  
    43.  
    44.  
    45.         }
    46.     }
    47.     void setCountText() {
    48.         countText.text = "Count: " + count.ToString();
    49.  
    50.     }
    51. }
    52.  
     
    Last edited: Aug 9, 2016
  20. Deleted User

    Deleted User

    Guest

    Please post your script using the proper code tags: http://forum.unity3d.com/threads/using-code-tags-properly.143875/
     
  21. andyace

    andyace

    Joined:
    Aug 9, 2016
    Posts:
    4
  22. Deleted User

    Deleted User

    Guest

    To add a skybox, see here, scroll down to "Scene Tab": http://docs.unity3d.com/Manual/GlobalIllumination.html (click on the circle on the right of "skybox" and choose "defaultskybox".

    To add a light to the scene, right click in the hierarchy view, go down to "light" in the contextual menu and then choose "directional light". Same thing to add a camera.
     
  23. Deleted User

    Deleted User

    Guest

    It's a problem that seem to happen a lot lately and it may be due to using the latest versions of Unity. Make sure the "countText" property has been filled in the Inspector window. :)

    Oh, I forgot: make sure the PlayerController script has not been added to several objects.
     
  24. andyace

    andyace

    Joined:
    Aug 9, 2016
    Posts:
    4
    The PlayerController script is only added to player, nothing else, the countText property does not appear in the inspector for text... Thank you for your help btw!
     
  25. Deleted User

    Deleted User

    Guest

    The property is absent or it's empty? If it's empty, add the countText from the hierarchy window.
     
  26. andyace

    andyace

    Joined:
    Aug 9, 2016
    Posts:
    4
    I found it , its here: upload_2016-8-9_10-3-13.png I still get the same error though :( as It does not appear in the hierarchy..
     
    Last edited: Aug 9, 2016
  27. Sw00d

    Sw00d

    Joined:
    Aug 8, 2016
    Posts:
    2
    thank you for the help, my question is how do I make the sun cast shadows or put it so it's realistic?
     
  28. albertogt

    albertogt

    Joined:
    Aug 10, 2016
    Posts:
    2
    Hello, i try but the ball dont stop in the wall, and when activate gravity the ball falling down
     
  29. OboShape

    OboShape

    Joined:
    Feb 17, 2014
    Posts:
    836
    Check that u have a collider on the player ball, and that is not set to trigger collider.

    Also, if the player does have collider and it is still falling through the ground. Check that the floor has a non trigger collider and the ball is off the ground.
     
  30. Deleted User

    Deleted User

    Guest

    It should be in the hierarchy view; it's a GUI you should have created in a previous lesson. If it's not there, you'll have to make it. :)
     
  31. albertogt

    albertogt

    Joined:
    Aug 10, 2016
    Posts:
    2
    Thanks i had player collider with a trigger collider checked when i uncheck work fine, I thought player ball fired event when colllision to box but is inverse box fired event
     
  32. amandamontanapearce

    amandamontanapearce

    Joined:
    Aug 11, 2016
    Posts:
    3
    Hi I've been going through the tutorial (though I am writing my code in js), and I think everything is working, but when I was setting up movement I rolled the ball off the plane and now it seems lost, whenever I hit play. Ideally I would like the ball to start back on the plane each time I hit play. I'm very new to Unity and don't quit understand how everything works ... but I think my ball is just falling. When I hit play and inspect the player(ball) the y position is something crazy like -2000 and growing. This has made it very hard to figure out what is working and what is not. I've considered the idea of trying to use player.transform.translate in start but to no avail. I'm not even sure if that is my issue since when I hit play the game appears to start from where it left off. Is there anyway to play the game as I'm developing it from the beginning where the ball was originally placed?
    Code (JavaScript):
    1. import UnityEngine;
    2. import System.Collections;
    3. import System;
    4. class PlayerController extends MonoBehaviour {
    5.     var speed = 800.0;
    6.     var player : GameObject;
    7.     function Start () {
    8.     player.transform.Translate(1,1,1);
    9.     }
    10.     function FixedUpdate() {
    11.     var moveHorizontal : float = Input.GetAxis("Horizontal");
    12.     var moveVertical : float = Input.GetAxis("Vertical");
    13.     var movement = Vector3(moveHorizontal, 0.0f, moveVertical);
    14.     GetComponent.<Rigidbody>().AddForce(movement * speed * Time.deltaTime);
    15.     }
    16. }
    17.  
     
  33. mattrodo

    mattrodo

    Joined:
    Aug 12, 2016
    Posts:
    1
    I have a problem. I'm on the "Displaying the score and text" and I'm getting an error i cant fix.

    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using UnityEngine.UI;
    4. using System.Collections;
    5.  
    6. public class PlayerController : MonoBehaviour {
    7.  
    8. public float speed;
    9. public Text countText;
    10. public Text winText;
    11.  
    12. private Rigidbody rb;
    13. private int count;
    14.  
    15. void Start ()
    16. {
    17. rb = GetComponent<Rigidbody>();
    18. count = 0;
    19. SetCountText ();
    20. winText.text = "";
    21. }
    22.  
    23. void FixedUpdate ()
    24. {
    25. float moveHorizontal = Input.GetAxis ("Horizontal");
    26. float moveVertical = Input.GetAxis ("Vertical");
    27.  
    28. Vector3 movement = new Vector3 (moveHorizontal, 0.0f, moveVertical);
    29.  
    30. rb.AddForce (movement * speed);
    31. }
    32.  
    33. void OnTriggerEnter(Collider other)
    34. {
    35. if (other.gameObject.CompareTag ( "Pick Up"))
    36. {
    37. other.gameObject.SetActive (false);
    38. count = count + 1;
    39. SetCountText ();
    40. }
    41. }
    42.  
    43. void SetCountText ()
    44. {
    45. countText.text = "Count: " + count.ToString ();
    46. if (count >= 12)
    47. {
    48. winText.text = "You Win!";
    49. }
    50. }
    51. }
    52.  
    My Error message: NullReferenceException: Object reference not set to an instance of an object PlayerMovement.SetCountText () at (Assets/Scripts/PlayerMovement.cs:44)

    If my googling was correct that should mean there was something on line 44 doesn't exist yet but I can't find what.
     
  34. Deleted User

    Deleted User

    Guest

    OboShape likes this.
  35. dmarin

    dmarin

    Joined:
    Aug 16, 2016
    Posts:
    1
    Hi, new here.

    I've been following the Roll a Ball tutorial with great interest, but there is a question that is itching me.
    Why does the ball collide with the plane and doesn't fall due to gravity but the Pick Up cubes just go through the plane when let be pulled by gravity?
     
  36. Crazyrzy

    Crazyrzy

    Joined:
    Jun 6, 2016
    Posts:
    1
    Hi i have a Problem where when i Build the Game and Run it, i can't collect the balls while in Unity (where i test the game) it does.
     
  37. OboShape

    OboShape

    Joined:
    Feb 17, 2014
    Posts:
    836

    Evening,

    See if we cant get you moving around, i dont know JS at all, but heres a generalisation that may help.

    Ok so starting off in the scene view in the editor.
    when you place/create objects in here this will be considered their starting positions (When NOT in play mode)

    when you press Play it starts running the game, ie scripts on gameobjects start running, physics starts working etc..

    if you press stop, Play mode is exited, and you return to the editor with all the objects etc i the same state and position they were in prior to you pressing Play as any changed made within play mode are not retained.

    you have the controls at the top for Play, Pause and Step. what to do is press Pause, and then press Play. this will allow you to see the first frame of the game, check where the player ball is, is it in the place where it should be?
    (possibly comment out the transform.translate line)

    you can then press the Step button (right of pause) you can then step through each frame and see what the ball is actually doing, is it falling through the ground? does it go off in a strange direction, or moved really fast?

    try lowering the speed value down to 5 and see what happens, i think 800 is too fast)

    see how you get on with pausing, then pressing play and stepping through frames to see what is going on initially.
     
  38. OboShape

    OboShape

    Joined:
    Feb 17, 2014
    Posts:
    836
    its to do wth the collider that is on the objects.

    with the player ball, it has a collider that does not have the 'is trigger' ticked, so this will interact with physical collisions, so the ball contacts another collider (the floor) and doesnt go through it.

    the pickup has a collider, that has a tick in 'is trigger', which basically means that nothing will physically collide with it, but you can get notified if another collider enters the trigger volume.
     
  39. OboShape

    OboShape

    Joined:
    Feb 17, 2014
    Posts:
    836
    do you only have one scene in your game? can you still move around as normal when you build it?
    with the scene that works open, if you go to File > Build Settings, delete the scene that is in there, then click 'Add Open scenes' might have another scene in there that doesnt work properly.
     
  40. Ferro111

    Ferro111

    Joined:
    Aug 16, 2016
    Posts:
    1
    Hi there. I have a question: I have a green sphere on my test level that is the "end" of the level, but on collision, I want it to display a menu asking if the player wants to restart the level.

    So does anyone have a script I can use for this? Thanks!
     
  41. OboShape

    OboShape

    Joined:
    Feb 17, 2014
    Posts:
    836
    if you work through the Tic Tac Toe tutorial there is a restart button used in it that may give you pointers.
    http://unity3d.com/learn/tutorials/tic-tac-toe/restarting-game?playlist=17111
     
  42. herano

    herano

    Joined:
    Aug 20, 2016
    Posts:
    4
    Hello hello. I have a small issue. Part 2 of the tutorial tells me to hover above input and press (ctrl plus ') to open the unity documentation, but does does not seem to work. Instead it opens the team explorer. What am I doing wrong? Thanks for any answers!

    I also keep having this error: rc.right == m_GfxWindow->GetWidth() && rc.bottom == m.GfxWindow->GetHeight() How do i fix this and is there an easy way to know what errors mean in general? Update: The error is away now but I am still curious to what it meant.

    Had some problems with my code, but found the solutions. Feels good:).
     
    Last edited: Aug 20, 2016
  43. OboShape

    OboShape

    Joined:
    Feb 17, 2014
    Posts:
    836
    Nice one that you are finding solutions as you work through ;)

    for the ctrl + ' , it may be to do with the way that the shortcuts are set up, im asuming that your working with visual studio instead of MonoDevelop?

    that particular shortcut im assuming opens the Team Explorer for visual studio.
    see if this helps you out to try and get the scripting guide opening for that shortcut
    http://forum.unity3d.com/threads/getting-ctrl-to-work-within-vs.372584/#post-2724713

    as for the error you are getting, Ill have to work through the project again before I comment on that.
     
  44. Ohmeoh

    Ohmeoh

    Joined:
    Aug 20, 2016
    Posts:
    2
    Hello!

    So I got unity a few days ago and have been trying to complete this Roll A Ball. I have re started ... can't even count anymore how many times! I have no problem keeping up and understand but ALL the time, the script works and the next minute it won't. 100% of the time it loses it's Mono, Player Object, and more. Please tell me why?
     
  45. OboShape

    OboShape

    Joined:
    Feb 17, 2014
    Posts:
    836
    Sorry, are you able to describe a single error that you are getting, maybe try and work through them one at a time.
    By scripts not working, is that not working after being edited and then returning to the editor?
    Is Tha the same time you get the 'no monobehaviour' error on the component?

    Generally this would indicate syntax/parsing problems with the script.

    Could you elaborate slightly what is happening by losing the player please.
     
  46. herano

    herano

    Joined:
    Aug 20, 2016
    Posts:
    4
    Thanks for the help! I cant get the ctrl + ' to work yet, but I finished the rest of the Roll-A-Ball project without a lot of trouble. You rock!
     
  47. CCPM

    CCPM

    Joined:
    Aug 22, 2016
    Posts:
    7
    I'm having an issue with the 'collecting the pickups' part of the tutorial. when i went to copy the piece of code from GameObject.CompareTag, rather than having the code shown in the tutorial, it had this:
    using UnityEngine;
    using System.Collections;

    public class ExampleClass : MonoBehaviour {
    void OnTriggerEnter(Collider other) {
    if (other.gameObject.CompareTag("Player"))
    Destroy(other.gameObject);

    }
    }
    and so it made it difficult for me from there on out to follow the tutorial steps, but i followed them as closely as i could. But then, once i got to the part where it says to test it and enter play mode, i tried but couldn't even go into play mode because it says that 'all compiler errors have to be fixed before you can enter play mode!'. The tutorial video says to check for errors but it never shows me how or where to do so, or at least not that I can see. I think the difference in code explained before might be the error, but i'm not sure and i don't know how to check for errors, so if anyone could help me with this so i can complete the project, that would be much appreciated!
     
  48. herano

    herano

    Joined:
    Aug 20, 2016
    Posts:
    4
    I had this problem too and the problem might not be in in the code itself, but in the formatting (as far as I understand). Whenever I have this problem I go in visual studio to edit -> advanced save options -> line endings and set them to windows (as i am making it on windows). There is probably a better solution to this problem because I had to do it every time I changed something, but I finished the tutorial with this makeshift solution, so maybe you can continue now too for now^^.

    I am also curious to what the more long term solution might be, OboShape:).

    I also have a small question left about the 'Win text'. Every time I play it in 'playmode' the text appears on the right spot. But when I build the game and play the text appears closer to the ball and more to the left. I also wanted to make it a bit bigger, but the the words appeared underneath each-other and not beside when I made the front bigger. What should I do to change that?
     
    Last edited: Aug 22, 2016
  49. OboShape

    OboShape

    Joined:
    Feb 17, 2014
    Posts:
    836
    Evening, the tutorial uses the gameObject.CompareTag in the script. probably best to go along with the tutorial as-is to get your feet wet so to speak, and then once done, go back and make tweaks and look at changes.

    Firstly, the section of code you have there is from the scripting API reference guide.
    Whilst a great source of information, it should be taken in context, its main purpose there is simply showing an example on how to use the CompareTag method inside OnTriggerEnter within an arbitrary script.

    if you were to place that section of code within your PlayerController script, it wont work, heres some info as to why..

    Now, in this tutorial these checks are done within the playerController script.
    a caveat of the MonoBehaviour script is that the class name in the script, must match the scripts filename or it will not compile, and just tell you that it cannot find the associated script ( which will be indicated in the inspector, if you have the game objeft it is attached to selected)

    so sticking with the tutorial you can see that the filename is PlayerController.cs and the class name in the script is matching with
    Code (CSharp):
    1. public class PlayerController : MonoBehaviour {
    Regarding errors,
    any errors that are requiring attention should be seen in the console window. also the last error or warning can be seen in the lower left bar of the editor window.
    (if you cannot see the console window, go to Window > Console)
    Any error that shows in the console, you can double click it and it will go to the relavent script and section that caused the error (most of the time)
     
  50. CCPM

    CCPM

    Joined:
    Aug 22, 2016
    Posts:
    7
    Thanks, herano and OboShape! [-= But now I've run into another problem regarding errors. I now know how to go to them and double click to go to where the error is, but because I don't know the CSharp code language at all, I don't know how to fix these scripting errors properly, and this time I typed out the code in the tutorial exactly:

    using UnityEngine;
    using System.Collections;

    public class PlayerController : MonoBehaviour {

    public float speed;

    private Rigidbody rb;

    void Start ()
    {
    rb = GetComponent<Rigidbody> ();
    }

    void FixedUpdate ()
    {
    float moveHorizontal = Input.GetAxis ("Horizontal");
    float moveVertical = Input.GetAxis ("Vertical");

    Vector3 movement = new Vector3 (moveHorizontal, 0.0f, moveVertical);

    rb.AddForce (movement * speed);
    }
    }
    void OnTriggerEnter(Collider other)
    {
    if (other.gameObject.CompareTag("Pick Up"))
    {
    other.gameObject.SetActive (false);
    }
    }
    }

    But there are still 2 scripting errors showing up in my console, here's the first one: Assets/Materials/Scripts/PlayerController.cs(25,10): error CS0116: a namespace can only contain types and namespace declarations
    And when I double click it it takes me to this:

    void OnTriggerEnter(Collider other)

    And here's the second one:
    Assets/Materials/Scripts/PlayerController.cs(32,1): error CS8025: Parsing error
    And when I double click it it takes me to this:
    }

    Which is the very last thing at the end of this area of the script:
    }
    }
    void OnTriggerEnter(Collider other)
    {
    if (other.gameObject.CompareTag("Pick Up"))
    {
    other.gameObject.SetActive (false);
    }
    }
    }

    Hopefully you can tell me what to do with the script to fix it so i can enter play mode and test! Thanks!
     
    Last edited: Aug 23, 2016