Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice

rts - chopping down trees dilemma

Discussion in 'Scripting' started by dingaling007, Jun 25, 2017.

  1. dingaling007

    dingaling007

    Joined:
    Oct 27, 2016
    Posts:
    26
    I have a prefab tree which has its own animation controller for its leaves moving in a gentle breeze, and also an animation of the tree falling over when the player chops it down.

    Problem is only the original tree prefab plays the falling animation. If the player chops a clone prefab tree, it doesnt play the animation but it does destroy as intended.

    I'm probably doing this wrong. Perhaps its a bad idea to use an animation controller on an animated tree that is cloned? Perhaps i need to assign the animation controller to the tree on the fly targeted by the player somehow?






    basic tree code which gets called from another script:


    Code (CSharp):
    1. public class animatedpalm : MonoBehaviour {
    2.  
    3.     public Animator anim;
    4.  
    5.     public bool treefell = false;
    6.  
    7.  
    8.  
    9.     void Start () {
    10.         anim = this.GetComponent<Animator> ();
    11.    
    12.     }
    13.    
    14.  
    15.     void Update () {
    16.  
    17.         if (treefell)
    18.         {
    19.             treefallen ();
    20.         }
    21.         else
    22.         anim.Play("GentleBreeze");  
    23.     }
    24.  
    25.  
    26.     public void treefallen ()
    27.     {
    28.         anim.SetBool ("TreeFall", true);
    29.    
    30.     }
    31.  
    32. }
     
  2. WheresMommy

    WheresMommy

    Joined:
    Oct 4, 2012
    Posts:
    890
    Can you show us, where the function gets called? Like, when does the tree you are chopping right now know, that it is "destroyed"? I guess, you got a prefab somewhere and your attack is not combined with a trigger or raycast to check the right tree, so always the original will get affected?
     
  3. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    I like the little circle you have on the ground. How did you do that? :)

    I did a little test and it can work for multiple clones.
    As @asd234w4r5 said, as I was writing -- it would be good to see the rest of the relevant code. Perhaps you are referencing only 1 tree, and that's why it's not running the correct animation.
     
  4. dingaling007

    dingaling007

    Joined:
    Oct 27, 2016
    Posts:
    26


    Oops i should of included that code too, apologies for my coding, im still a learning newb.
    I think your right on the money with the issue. Im using:
    if (interactionInfo.collider.CompareTag ("Tree"))

    Which is the Tag on all my tree prefabs.
    Im not sure best how to set it up.



    Code (CSharp):
    1. private void moveToTree()
    2.     {
    3.     if(canMove)
    4.         {
    5.             Ray interactionRay = Camera.main.ScreenPointToRay(Input.mousePosition);
    6.             RaycastHit interactionInfo;
    7.  
    8.             if (Physics.Raycast (interactionRay, out interactionInfo, 500))
    9.             {
    10.             if (interactionInfo.collider.CompareTag ("Tree"))
    11.                 {
    12.                     moveTarget = interactionInfo.point;
    13.                     playerAgent.destination = interactionInfo.point;
    14.                     animator.SetBool ("isWalking", true);
    15.                     pathReached = false;
    16.                     GameObject hitObject = interactionInfo.transform.root.gameObject;
    17.                     SelectObject (hitObject);
    18.                     moveFSM = MoveFSM.choptree;





    Code (CSharp):
    1. private void choptree()
    2.     {
    3.         if(!playerAgent.pathPending)
    4.         {
    5.             if(Vector3.Distance(playerAgent.destination, this.transform.position) <1)
    6.                 {
    7.                     Vector3 dir = currentInteractable.transform.position - transform.position;
    8.                     dir.y = 0;
    9.                     rot = Quaternion.LookRotation (dir);
    10.                     transform.rotation = Quaternion.Lerp (transform.rotation, rot, 1f * Time.deltaTime);
    11.                     animpalm.voilentwinds = true;
    12.                     StartCoroutine (PlayChopInterval (1    , 3f));
    13.                  
    14.                 }
    15.         }
    16.     }





    Code (CSharp):
    1.     private IEnumerator PlayChopInterval(int n, float time)
    2.     {
    3.             animator.SetBool ("timetochop", true);
    4.             playerAgent.speed=0;
    5.             yield return new WaitForSeconds (time);
    6.  
    7.             animator.SetBool ("timetochop", false);
    8.             playerAgent.speed=8;
    9.             moveFSM = MoveFSM.idle;
    10.             animpalm.treefell = true;
    11.             DestroyObject (currentInteractable, 5f);
    12.  
    13.     }
     
    Last edited: Jun 25, 2017
  5. dingaling007

    dingaling007

    Joined:
    Oct 27, 2016
    Posts:
    26


    Thanks, that selection circle on the ground was from this tutorial here, i changed the graphic but it works well. I added the animated arrows myself to move to the ray cast click position and just to play the arrow animation once and dissapear.

    Yes you might be right, Im hoping with the above posted code it will become clear where ive gone wrong. Its probably obvious i just havent worked it out in my head yet.
     
    Last edited: Jun 25, 2017
  6. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    Thanks for posting that video. I will BM it to watch later :)

    Okay, so I can't be sure, but I feel like I'm going to repeat my earlier guess. I think you're not using the current selected object to call the animator (animation).

    When you 'chop', maybe use the 'selectobj' result/assignment.. then, get that object's Animator to play?

    I would be more specific, but I don't want to say the wrong thing about your code snippets.. but I'm almost certain that is the reason, in general terms :)
     
  7. dingaling007

    dingaling007

    Joined:
    Oct 27, 2016
    Posts:
    26
    Yeah your right methos5k, I was using: if (interactionInfo.collider.CompareTag ("Tree"))

    Forgive my newbness. So if i click on a tree, the raycast hit can report back what the hit object was, i would still need to use my "Tree" tag to know to then carry on with the chopping of the tree. But somehow select that object to grab its animation controller. I think i need to see some functional code to get my head around it :/
     
  8. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    I am not sure. So, you select the tree with a raycast when you're going to chop it down? Then, check if you're close enough & then proceed? Something like that?
    Whenever you're selecting, and it's a valid selection, simply GetComponent<ScriptName>() on the selected object and execute the method to begin chopping.
     
  9. dingaling007

    dingaling007

    Joined:
    Oct 27, 2016
    Posts:
    26
    Yes although Im not selecting the tree as so much as just testing if it has the tag "Tree". But yep thats how the tree chopping is setup.

    To make it a valid selection, would i need to cache the selected object somehow? I need to store the selection to then GetComponent<ScriptName>() Boy i have a lot to learn lol

    Thanks for your patience
     
    Last edited: Jun 25, 2017
  10. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    Okay. Well, even if you're testing your selection to see if it's tagged as "Tree", as you said.. that must mean you've hit a collider - and from there, you can GetComponent<ScriptName>() , attached to said "hit".
    That script should run the correct Animator/animation ;)
    Hopefully that makes sense. :)
     
  11. dingaling007

    dingaling007

    Joined:
    Oct 27, 2016
    Posts:
    26
    It makes alot of sense until i try to code it :(

    Code (CSharp):
    1.         Ray interactionRay = Camera.main.ScreenPointToRay(Input.mousePosition);
    2.             RaycastHit interactionInfo;
    3.  
    4.             if (Physics.Raycast (interactionRay, out interactionInfo, 500))
    5.             {
    6.             if (interactionInfo.collider.CompareTag ("Tree"))
    7.                 {
    8.  
    9.        
    10.                     Debug.Log ("tree clicked");
    11.                     moveTarget = interactionInfo.point;
    12.                     playerAgent.destination = interactionInfo.point;
    13.                     animator.SetBool("isIdle", false);
    14.                     animator.SetBool ("isWalking", true);
    15.                     pathReached = false;
    16.                     GameObject hitObject = interactionInfo.transform.root.gameObject;
    17.                     SelectObject (hitObject);
    18. //this didnt seem to work but im sure im missing out alot of info :/
    19.                     hitObject.GetComponents<animatedpalm>();
    20.                     moveFSM = MoveFSM.choptree;
    21.  
    22.                 }
     
  12. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    Ya, mostly there. So, you're missing (after <animatedpalm>()) you need ".NameOfMethodToCall()"
    :)
    Oh, and just GetComponent (no 's').
     
  13. dingaling007

    dingaling007

    Joined:
    Oct 27, 2016
    Posts:
    26

    Thanks very much methos5k i've learnt something powerful here! Its not perfect because the hit ray object only exists in that block of code when i need to use it in the co-routine. But i will play with it. At least now i know how to get the script from the targeted GameObject and call its script functions.
    :):):)
     
  14. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    Cool, glad I could help in some way(s). If you ever get stuck later, feel free to write, again. :) Take it easy, and good luck with your game =)
     
  15. dingaling007

    dingaling007

    Joined:
    Oct 27, 2016
    Posts:
    26
    Thanks methos5k. I hope unity have you on there payroll! invaluable!

    EDIT UPDATE: Answer was to use a bool.

    A small side effect I've noticed is when i click on a another tree while the chopping state is taking place, the newly selected tree falls over instead of the first tree. It makes sense why its happening. But code wise I think i need a way to disable selecting new game objects until the first selected tree has run through its falling over, then destroy state.

    Is there a common way of handling these sorts of problems?

    EDIT: Nevermind, the power of using Bools! :)
     
    Last edited: Jun 26, 2017
  16. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    Glad ya got it working :)