Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Move to position, wait, look, move to new poistion[Solved]

Discussion in 'Scripting' started by Troas, Jun 25, 2014.

  1. Troas

    Troas

    Joined:
    Jan 26, 2013
    Posts:
    157
    I'm trying to make a script that makes an AI get the current player position, look at that position, move there, wait, and repeat the process. The problem I have is currently instead of updating once he gets to the first position cached, he gets the position of the player every frame.

    SharpDevelopment provided me with the code below to get started:
    Code (CSharp):
    1. private Transform player, transform;
    2.         public float overshoot, waitingTime;
    3.         private Vector3 lastPlayerPosition;
    4.         private bool isWaiting;
    5.         private void Awake() {
    6.             player = GameObject.FindGameObjectWithTag( "Player" ).transform;
    7.             transform = transform;
    8.             lastPlayerPosition = player.position;
    9.         }
    10.         private void Update() {
    11.             //Either the players position hasnt changed or we are currently waiting
    12.             if( lastPlayerPosition == player.position || isWaiting ) return;
    13.             lastPlayerPosition = player.position;
    14.             transform.LookAt( player );
    15.             transform.position +=  ( player.position - transform.position ) + transform.forward*overshoot;
    16.             transform.LookAt( player );
    17.             StartCoroutine( Wait());
    18.         }
    19.         private IEnumerator Wait() {
    20.             isWaiting = true;
    21.             yield return new WaitForSeconds( waitingTime );
    22.             isWaiting = false;
    23.         }

    So my idea to modify it to where it does not update until he gets to the first position cached was to do as so:
    Code (CSharp):
    1. private Transform _player, _transform;
    2.     public float overshoot, waitingTime, moveSpeed;
    3.     private Vector3 _lastPlayerPosition;
    4.     private bool _isWaiting;
    5.     private float step = overshoot * moveSpeed * Time.deltaTime;
    6.    
    7.     private void Awake() {
    8.         GameObject player = GameObject.FindGameObjectWithTag( "Player" );
    9.         _player = player.transform;
    10.  
    11.         _transform = transform;
    12.        
    13.         _lastPlayerPosition = _player.position;
    14.     }
    15.    
    16.     private void Update() {
    17.  
    18.         //Either the players position hasnt changed or we are currently waiting
    19.         if( _isWaiting ) return;
    20.        
    21.         _lastPlayerPosition = _player.position;
    22.  
    23.         if (_transform.position == _lastPlayerPosition) {
    24.             StartCoroutine (Wait ());
    25.             _transform.LookAt (_player);
    26.             StartCoroutine (MoveToPlayer ());
    27.         } else {
    28.             StartCoroutine (MoveToPlayer ());
    29.         }
    30.     }
    31.  
    32.     private IEnumerator MoveToPlayer(){
    33.         _transform.LookAt (_player);
    34.         _transform.position = Vector3.MoveTowards (_transform.position, _player.position, step);
    35.     }
    36.  
    37.     private IEnumerator Wait() {
    38.         _isWaiting = true;
    39.         yield return new WaitForSeconds( waitingTime );
    40.         _isWaiting = false;
    41.     }
    The step float is just to smooth the movement towards the player, which I did successfully. However the code above does not work giving the error "Assets/TestAIScript.cs(12,30): error CS0236: A field initializer cannot reference the nonstatic field, method, or property `TestAIScript.overshoot'".

    Not too sure what this means but even if I understood it the logic above does not produce a movement that only updates for the new position only if the old position has been reached.
     
  2. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    8,738
    Basically what it's saying is that on this line:
    Code (csharp):
    1. private float step = overshoot * moveSpeed *Time.deltaTime;
    It's telling you that you can't use other variables to determine the default value; whatever you have there should be a constant.

    You can do all the math you want in Awake(), so initialize that to "0" on that line, and set its value elsewhere.

    There's other issues, though. Mainly, Time.deltaTime is meaningless during Awake(). It might even be zero, honestly, I'm not sure. The point is, Time.deltaTime is the time between this frame and the last one, and before the first frame starts that doesn't mean anything. Moreover, if the framerate changes, so will the movement speed of your AI, since it's still using the Time.deltaTime from the beginning of the game (which, again, is probably zero anyway)! You'll want to multiply in Time.deltaTime in the frame for which it's being used; there's no reason to store Time.deltaTime (or anything that it's been multiplied in to) across frames.

    All that said, multiplication is fast, so I wouldn't cache any of that math at all, honestly. Eliminate the 'step' variable and put overshoot * moveSpeed *Time.deltaTime directly into your MoveTowards function. That way, it will always reflect the current moveSpeed and overshoot values (in case those change at runtime, and if not, you only lose complexity anyway).
     
  3. Y0ko

    Y0ko

    Joined:
    Jun 25, 2014
    Posts:
    17
    hi

    hummmm i think instead of use coroutine you can use some enumeration.

    something like this:

    Code (CSharp):
    1. public enum Etat
    2.     {
    3.         goToPlayer,
    4.         wait,
    5.         lookAtPlayer
    6.     }
    7.     public Etat etat = Etat.goToPlayer;
    8.  
    9.     public float timeToWait = 2f;
    10.     private float timeToWaitReset;
    11.  
    12.     public Transform target;
    13.  
    14.  
    15.     // Use this for initialization
    16.     void Start () {
    17.    
    18.         timeToWaitReset = timeToWait;
    19.  
    20.     }
    21.    
    22.     // Update is called once per frame
    23.     void Update () {
    24.    
    25.         switch (etat) {
    26.         case Etat.goToPlayer:
    27.             GoToPlayer ();
    28.             break;
    29.         case Etat.wait:
    30.             Wait ();
    31.             break;
    32.         case Etat.lookAtPlayer:
    33.             LookAtMan ();
    34.             break;
    35.         }
    36.  
    37.     }
    38.  
    39.  
    40.     void GoToPlayer (){
    41.  
    42.         // ia go to the player
    43.  
    44.     }
    45.  
    46.     void Wait(){
    47.  
    48.  
    49.         // ia wait
    50.  
    51.         timeToWait -= Time.deltaTime;
    52.  
    53.         if(timeToWait <= 0)
    54.         {
    55.             etat = Etat.lookAtPlayer;
    56.             timeToWait = timeToWaitReset;
    57.         }
    58.     }
    59.  
    60.     void LookAtMan(){
    61.  
    62.         // ia look at the player
    63.     }
    64. }
     
  4. Sharp-Development

    Sharp-Development

    Joined:
    Nov 14, 2013
    Posts:
    353
    So you are basically saying that switch/if-else cluttery is more elegant than a simple coroutine?

    Considering you suggested states which infact lead to the fact of you suggesting FSM's (which I btw fully agree too).
    But seriously, building a FSM with switch's... ? Thats just not elegant at all... You'd be better of building it up with coroutine's and delegates.

    Coroutines are perfectly suited for the above case so no need to uselessly clutter up code.
     
  5. Y0ko

    Y0ko

    Joined:
    Jun 25, 2014
    Posts:
    17
    ok ok my bad :(
     
  6. Troas

    Troas

    Joined:
    Jan 26, 2013
    Posts:
    157
    Alright, I'll have to look up a bit more how to use coroutines as I still have trouble understanding them but I get the jist.

    My only problem is I did do the above suggested:

    Code (CSharp):
    1. moveSpeed * overshoot * Time.Deltatime
    and it just ended up being a follow AI with a wait time for each and every single frame, which ended up being a jerky movement.

    I'm still trying to figure out how to make it find a position during the update and go to that position first before ever finding a new position and going there. So the player could move and the AI would still be going to the last known position until it finally reaches it.


    So while the float step thing is removed and solved I guess I'm asking if my basic logic using the if else with the coroutines is even right at all?

    Code (CSharp):
    1. void Update(){
    2.  
    3. if (myPosition = playerPosition) {
    4. StartCoroutine (Wait());
    5. }else{
    6. StartCoroutine (GoToPlayer());
    7. }
    8.  
    9. private IEnumerator GoToPlayer(){
    10. // Find player position
    11. // Go to position + overshoot
    12. }
    13.  
    14. private IEnumerator Wait(){
    15. // Wait this amount of time
    16. }
    I'm just confused on how to tell it to completely transform its position to the current players position before getting the new one.
     
    Last edited: Jun 25, 2014
  7. Sharp-Development

    Sharp-Development

    Joined:
    Nov 14, 2013
    Posts:
    353
    1. Fetch the current position of the player and cache it, dont update it anymore after this
    2. Let the enemy look at this position
    3. Offset the cached player position by enemy.transform.forward*overshoot
    4. Move your enemy every update by forward*movespeed*Time.deltaTime
    5. Check if Vector3.Dot( forward, targetPos - enemy.transform.position ) < 0
    6. If so, start the coroutine and wait.
    7. Go to step 1

    As of this:
    Vector3.Dot( forward, cachedAndOvershootedPos - enemy.transform.position ) < 0
    If the resulting dot product is positive, the forward vector is pointing towards the target position, if negative the forward vector is pointing away from the target position and is therefore behind your enemy. ;)
     
    Last edited: Jun 25, 2014
  8. Troas

    Troas

    Joined:
    Jan 26, 2013
    Posts:
    157

    Ah ok that makes a lot more sense, sorry for having a whole thread about this, I know you pm'd me the Vector3.Dot method but I wasn't aware this was how to use it.

    I'll try uploading a video when I try it tonight.
     
  9. Sharp-Development

    Sharp-Development

    Joined:
    Nov 14, 2013
    Posts:
    353
    No worries ;)

    /E: Btw just noticed:
    4. Move your enemy every update by forward*movespeed*Time.deltaTime
     
  10. Troas

    Troas

    Joined:
    Jan 26, 2013
    Posts:
    157
    Code (CSharp):
    1. public float moveSpeed;
    2. public float waitTime;
    3.  
    4. private Transform lastPlayerPositon;
    5. private Transform overshotPosition;
    6. private Transform enemyPosition;
    7. private Transform transform;
    8.  
    9. void Start () {
    10.   player = GameObject.FindObjectWithTag("Player").transform;
    11.   playerPosition = player.position;
    12.   transform = transform;
    13.   enemyPosition = Transform.position;
    14. }
    15.  
    16. void Update () {
    17.   lastPlayerPosition = playerPosition;
    18.  
    19.   transform.LookAt(lastPlayerPosition);
    20.  
    21.   overshotPosition = (lastPlayerPosition - enemyPosition) * transform.forward * overshoot;
    22.  
    23.   enemyPosition += overshotPosition * moveSpeed * Time.Deltatime;
    24.  
    25.   if (Vector3.Dot(forward, lastPlayerPosition - smoothToPosition) < 0) {
    26.     Coroutine( Wait());
    27.   }
    28. }
    29.  
    30. private IEnumerator Wait () {
    31.   yield return new WaitForSeconds(waitTime);
    32. }
    33.  
    34.  
    It's very noobish code and definitely could be much more optimized but this is my first go at it, hopefully it is right.
     
    Last edited: Jun 26, 2014
  11. Sharp-Development

    Sharp-Development

    Joined:
    Nov 14, 2013
    Posts:
    353
    Code (CSharp):
    1. private bool _isWaiting;
    2.     public float moveSpeed, overshoot, waitTime;
    3.  
    4.     private Transform _playerTransform, _transform;
    5.     private Vector3 _targetPosition, _forward;
    6.  
    7.  
    8.     void Start () {
    9.         _playerTransform = GameObject.FindGameObjectWithTag("Player").transform;
    10.         _transform = transform;
    11.  
    12.         UpdateMovement();
    13.     }
    14.  
    15.     void Update () {
    16.         if( _isWaiting ) return;
    17.  
    18.         _transform.position += _forward*moveSpeed*Time.deltaTime;
    19.  
    20.         if ( Vector3.Dot( _forward, _targetPosition - _transform.position ) < 0 ) {
    21.             StartCoroutine( Wait());
    22.         }
    23.     }
    24.  
    25.     void UpdateMovement() {
    26.         _transform.LookAt( _playerTransform );
    27.         _forward = _transform.forward;
    28.         _targetPosition = _playerTransform.position + _forward*overshoot;
    29.     }
    30.  
    31.     private IEnumerator Wait () {
    32.         _isWaiting = true;
    33.         yield return new WaitForSeconds(waitTime);
    34.         UpdateMovement();
    35.         _isWaiting = false;
    36.     }
    37.  
     
  12. IsGreen

    IsGreen

    Joined:
    Jan 17, 2014
    Posts:
    206
    Anyway, if you prefer to use corroutines in your IA or game tasks, you should consider some situations in the game:

    -Game pause.
    -Slow or fast time.
    -Or instant cancellation of the game (the player dies, etc ...).
     
  13. Sharp-Development

    Sharp-Development

    Joined:
    Nov 14, 2013
    Posts:
    353
    Those situations should definitly be considered, but any other approach does carry the same need of handling. And its not to hard to implement the above handling. ;)
     
  14. IsGreen

    IsGreen

    Joined:
    Jan 17, 2014
    Posts:
    206
    But you must do it if you want to use a corroutine with yield WaitForSeconds, or gameobject is destroyed per example.

    I prefer to use Enumeration States: Pause, attack, follow... etc... and timer variable, in main MonoBehaviour Component(script).
     
  15. Sharp-Development

    Sharp-Development

    Joined:
    Nov 14, 2013
    Posts:
    353
    Yes, in other words a FSM. However, it doesnt matter if you use a coroutine or not, you will always have to do such checks no matter with what approach you go.
     
  16. Troas

    Troas

    Joined:
    Jan 26, 2013
    Posts:
    157
    Code (CSharp):
    1. private bool _isWaiting;
    2.     public float moveSpeed, overshoot, waitTime;
    3.  
    4.     private Transform _playerTransform, _transform;
    5.     private Vector3 _targetPosition, _forward;
    6.  
    7.  
    8.     void Start () {
    9.         _playerTransform = GameObject.FindGameObjectWithTag("Player").transform;
    10.         _transform = transform;
    11.  
    12.         UpdateMovement(); // How come this is in start and not update? Doesn't this mean it only happens once?
    13.     }
    14.  
    15.     void Update () {
    16.         if( _isWaiting ) return;
    17.  
    18.         _transform.position += _forward*moveSpeed*Time.deltaTime;
    19.  
    20.         if ( Vector3.Dot( _forward, _targetPosition - _transform.position ) < 0 ) {
    21.             StartCoroutine( Wait());
    22.         }
    23.     }
    24.  
    25.     void UpdateMovement() {
    26.         _transform.LookAt( _playerTransform );
    27.         _forward = _transform.forward; // So you need this in order to use the comparing method "Vector3.Dot" above, correct?
    28.         _targetPosition = _playerTransform.position + _forward*overshoot; // So basically this needs to calculate and cache before the movement happens at all
    29.     }
    30.  
    31.     private IEnumerator Wait () {
    32.         _isWaiting = true;
    33.         yield return new WaitForSeconds(waitTime);
    34.         UpdateMovement();
    35.         _isWaiting = false;
    36.     }
    37.  
    Just put in comments a few things that confuse me, thanks guys for helping so much hopefully I didn't make it feel like you guys made the code for me but I'll definitely credit you SharpDev.

    I think I need to go look up the difference b/w Awake() and Start(). I remember it explained once to me but don't quite remember what it was.

    If I understand correctly, the difference between regular methods and coroutines is that Coroutines can yield at any moment where as methods cannot. Correct?

    So basically these are all game managing implementations that I need to consider when using any sort of method/coroutine that relies on updating every frame?

    If I am understanding what an FSM is, it's basically code that allows you to determine every single possible state your objects in the program could be and define what those states are. Correct?

    It all seems a bit over my head right now but I'm sure I can understand it with some work.
     
    Last edited: Jun 26, 2014
  17. Sharp-Development

    Sharp-Development

    Joined:
    Nov 14, 2013
    Posts:
    353
    Clearing up the comments at first :p

    1. UpdateMovement() in Start()
    -> Since we have to setup everything at startup we aswell call UpdateMovement() since that method caches every value we need. UpdateMovement is btw aswell called after waiting for a certain time. Just see the Wait() method, we aswell call it there and make sure everything is up to date and cached for the next movement period.
    If you would put this into update:
    a) Where your wait coroutine is called: It'll start with an empty target position and no forward vector. In other words, the object wouldnt know where to move since nothing is set and the condition of the object being behind the targetposition would be never met.
    b) At the beginning of Update(): Your object would always move in direction of the current player position. In other words, it would follow the player.
    2. _forward is used to check if the enemy is behind the target position. You could aswell call _transform.forward every time. However, thats somehwat costy so we cache the forward direction.
    3. Correctly, otherwise we wouldnt know where to move. When updating it every frame, your object would follow the player.


    Awake is called before anything else happens. First Awake of every object is called. After that Start() of every object is called. To note is that when disabling an object, the start method wont be called at all but awake will.

    Yes they are paused untill the next frame.

    http://unitygems.com/fsm1/[/code][/QUOTE]
     
  18. Troas

    Troas

    Joined:
    Jan 26, 2013
    Posts:
    157
    This is actually the problem I was experiencing at the beginning of this coding process. It makes sense now that I see it.

    As for #1 I see that I completely misunderstood how Scripts work. I thought they only read start once when the entire game started. Now I see they initialize at the start of whenever they are called, yet everything under Start() is only used once every time it's initialized while Update() can be done multiple times in one initialization. Each script can be initialized multiple times inside a game (IE. whenever it's needed). Correct?

    [To go further if I understand this correctly, anything in Awake() is called at the very beginning of the program and does not experience an update but is rather used for values that will be static and have scripts that rely on those values.]

    Basically I thought Start() could only be called once at the very start of the program so I didn't understand how you could possibly get the new position after the enemy reached the first one b/c I thought start would never call again. Thanks for clearing that up!

    Also I already started looking at the FSM from gems but thanks for the link, it appears I need to learn Quaternions as well. Oh boy.
     
  19. Sharp-Development

    Sharp-Development

    Joined:
    Nov 14, 2013
    Posts:
    353
    Uh dont get me wrong. Start, Awake and Update a normal methods. You can call them yourself. However, Awake and Start get called once by unity when the scene is loaded. Update gets called every frame.

    In our example we use the UpdateMovement() method for caching values. Values need to be cached once at start up in order for the object to have a target position. So we call UpdateMovement() once in Start().
    However, after that Start() will never be called again except when you are calling the method yourself.
    Any further updating of the current target position via UpdateMovement() is done in the coroutine after the object has waited a certain amount of time.
     
  20. Troas

    Troas

    Joined:
    Jan 26, 2013
    Posts:
    157
    Okay lol I guess I looked at it the wrong way haha, my bad.

    EDIT: I completely skimmed over the coroutine inside of Wait, now I see how it works haha, oopse
     
    Last edited: Jun 26, 2014
  21. Troas

    Troas

    Joined:
    Jan 26, 2013
    Posts:
    157
    So for now trying to make a script that is a one stop for the entire AI system:

    Code (CSharp):
    1. // Credit: SharpDevelopment for overshoot method
    2. // Attach to Enemy Prefab
    3. // Place in Assets/Scripts
    4. // Created 6/19/2014
    5. // Last Update 6/26/2014
    6.  
    7. using UnityEngine;
    8. using System.Collections;
    9.  
    10. public class Patrol : GameManager {
    11.    
    12.     public float moveSpeed;
    13.  
    14.     // Last Position Navigation variables
    15.     private Transform _playerTransform, _transform;
    16.     private Vector3 _targetPosition, _forward;
    17.     private bool _isWaiting;
    18.     public float overshoot, waitTime;
    19.  
    20.     // Point Array Navigation
    21.     public Transform[] patrolPoints;
    22.     private int currentPoint;
    23.  
    24.     // Follow Player Navigation variables
    25.     public Transform target;
    26.     public Vector3 targetPosition;
    27.     private Transform enemyTransform;
    28.  
    29.     void Start () {
    30.  
    31.         if (currentLevel == 0) {
    32.             _playerTransform = GameObject.FindGameObjectWithTag ("Player").transform;
    33.             _transform = transform;
    34.  
    35.             UpdateMovement ();
    36.         }
    37.  
    38.         if (currentLevel == 1) {
    39.             //Locate Patrol Points
    40.             transform.position = patrolPoints [0].position;
    41.             currentPoint = 0;
    42.         }
    43.  
    44.         if (currentLevel == 2) {
    45.             // Locate Player
    46.             GameObject player = GameObject.FindGameObjectWithTag("Player");
    47.             target = player.transform;
    48.  
    49.             // Locate Player Position
    50.             targetPosition = player.transform.position;
    51.  
    52.             // Enemy Current Position
    53.             GameObject enemy = this.gameObject;
    54.             enemyTransform = enemy.transform;
    55.         }
    56.     }
    57.    
    58.  
    59.     void Update () {
    60.  
    61.         if (currentLevel == 0) {
    62.             if (_isWaiting)
    63.                     return;
    64.  
    65.             _transform.position += _forward * moveSpeed * Time.deltaTime;
    66.  
    67.             if (Vector3.Dot (_forward, _targetPosition - _transform.position) < 0) {
    68.                     StartCoroutine (Wait ());
    69.             }
    70.         }
    71.  
    72.         if (currentLevel == 1) {
    73.             // Follow Player Indefinitely [Works]
    74.             transform.LookAt (target);
    75.             enemyTransform.position += enemyTransform.forward * moveSpeed * Time.deltaTime;
    76.         }
    77.  
    78.         if (currentLevel == 2) {
    79.             // Array Point Navigation [Works]
    80.             if (transform.position == patrolPoints [currentPoint].position) {
    81.                     currentPoint ++;
    82.             }
    83.  
    84.             if (currentPoint >= patrolPoints.Length) {
    85.                     currentPoint = 0;  
    86.             }
    87.  
    88.             transform.position = Vector3.MoveTowards (transform.position, patrolPoints [currentPoint].position, moveSpeed * Time.deltaTime);
    89.         }
    90.     }
    91.  
    92.     // Updates player position and calculates the overshot position
    93.     void UpdateMovement() {
    94.         _transform.LookAt( _playerTransform );
    95.         _forward = _transform.forward;
    96.         _targetPosition = _playerTransform.position + _forward*overshoot;
    97.     }
    98.  
    99.     // Used in conjuction with the UpdateMovement() method to create a "dumb" AI with waiting time
    100.     private IEnumerator Wait () {
    101.         _isWaiting = true;
    102.         yield return new WaitForSeconds(waitTime);
    103.         UpdateMovement();
    104.         _isWaiting = false;
    105.     }
    106. }
    107.  
    If interested here is the game manager code:

    Code (CSharp):
    1. // Attach to empty object in scene
    2. // Created 6/19/2014
    3. // Last Updated 6/25/2014
    4.  
    5. using UnityEngine;
    6. using System.Collections;
    7.  
    8. public class GameManager : MonoBehaviour {
    9.  
    10.     public static int currentScorer;
    11.     public static int highScorer;
    12.  
    13.     public static int currentLevel = 0;
    14.     public static int unlockedLevel;
    15.  
    16.     public Rect timerRect;
    17.  
    18.     public GUISkin skin;
    19.  
    20.     public float startTime;
    21.     private string currentTime;
    22.  
    23.     void Update (){
    24.         startTime -= Time.deltaTime;
    25.         currentTime = string.Format("{0:0.00}", startTime) ;
    26.     }
    27.  
    28.     void Start(){
    29.         DontDestroyOnLoad (gameObject);
    30.         Debug.Log ("I'm Here");
    31.     }
    32.  
    33.     public static void CompleteLevel() {
    34.  
    35.         if (currentLevel < 2) {
    36.             currentLevel += 1;
    37.             Application.LoadLevel (currentLevel);
    38.         }else{
    39.             print ("You Win!");
    40.         }
    41.     }
    42.  
    43.     void OnGUI(){
    44.         GUI.Label (timerRect, currentTime);
    45.     }
    46. }
    47.  
    48.  
    Just wondering if the if statements for checking what the current level is and setting the AI accordingly is good enough for now.. at least until I figure out FSM.
     
  22. Sharp-Development

    Sharp-Development

    Joined:
    Nov 14, 2013
    Posts:
    353
    I'd use switch or if-elseif instead but yea dont worry, it is for now. You can come back later and just enhance this. :p
     
  23. Troas

    Troas

    Joined:
    Jan 26, 2013
    Posts:
    157
    The only thing is 2 issues occur:

    The point array navigation is failing because some of the variables are getting confused (had this error before). What is the best practice for making variables that are similar? Or do I have too many at this point?

    The gamemanager public variables are now appearing on the patrol script which I do not want. Is this where I use protected variables so it only appears on the gamemanager?
     
  24. Sharp-Development

    Sharp-Development

    Joined:
    Nov 14, 2013
    Posts:
    353
    Scope your variables as private if you dont want them to be inherited by your derived classes.
    In general you should always mark any field as private and create getters/setters.
     
  25. Troas

    Troas

    Joined:
    Jan 26, 2013
    Posts:
    157
    So I can make them private and the create a get/set that appears in the component editor of the inspector for that script?
     
  26. NomadKing

    NomadKing

    Joined:
    Feb 11, 2010
    Posts:
    1,461
  27. Troas

    Troas

    Joined:
    Jan 26, 2013
    Posts:
    157
    Oh wow thank you, I couldn't remember what the command was called haha.
     
  28. Sharp-Development

    Sharp-Development

    Joined:
    Nov 14, 2013
    Posts:
    353
    [SerializeField] will make your private variables serialize and show in the editor. ;)
     
    Troas likes this.
  29. Troas

    Troas

    Joined:
    Jan 26, 2013
    Posts:
    157

    Any links to this little useful commands somewhere? I've gone through loads of tutorials and never heard of this one.
     
  30. Sharp-Development

    Sharp-Development

    Joined:
    Nov 14, 2013
    Posts:
    353
  31. Troas

    Troas

    Joined:
    Jan 26, 2013
    Posts:
    157
  32. Sharp-Development

    Sharp-Development

    Joined:
    Nov 14, 2013
    Posts:
    353
    Just browse throught the scripting API. You'll find lots of interesting stuff :D
     
  33. Troas

    Troas

    Joined:
    Jan 26, 2013
    Posts:
    157
    Oh man that's daunting well it was bound to happen, thanks for all the help y'all