Search Unity

How can I make the player stop moving?

Discussion in 'Scripting' started by DustyShinigami, May 17, 2019.

  1. DustyShinigami

    DustyShinigami

    Joined:
    Jan 5, 2018
    Posts:
    529
    The idea is, when the player starts talking to an NPC, I want all movement functions to stop. I've sort of done it in my script, but the character can still move on the spot, whether facing up, left or right. I've even tried setting the Vector3 to 0, 0, 0 for both moveHorizontal and moveVertical. How can I stop movement altogether? Thanks.

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.SceneManagement;
    5.  
    6. public class PlayerController : MonoBehaviour
    7. {
    8.     public Animator anim;
    9.     public float moveSpeed;
    10.     public float jumpForce;
    11.     public bool jumped;
    12.     public bool attack;
    13.     public static bool interact = false;
    14.     public static bool allowInteract = false;
    15.     public float gravityScale;
    16.     public float knockBackForce;
    17.     public float knockBackTime;
    18.     public float invincibilityLength;
    19.     public Renderer playerRenderer;
    20.     public Material textureChange;
    21.     public Material textureDefault;
    22.     public bool allowCombat;
    23.     public bool allowJump;
    24.     public bool notDestroyed;
    25.     public bool canMove;
    26.  
    27.     private Vector3 moveDirection;
    28.     private Vector3 extraDirections;
    29.     private float knockBackCounter;
    30.     private float invincibilityCounter;
    31.     private CharacterController controller;
    32.  
    33.     void Start()
    34.     {
    35.         Cursor.visible = false;
    36.         controller = GetComponent<CharacterController>();
    37.         canMove = true;
    38.         if (SceneManager.GetActiveScene() == SceneManager.GetSceneByName("start_area"))
    39.         {
    40.             allowCombat = false;
    41.             allowJump = true;
    42.         }
    43.         if (SceneManager.GetActiveScene() == SceneManager.GetSceneByName("hut_interior"))
    44.         {
    45.             allowCombat = false;
    46.             allowJump = false;
    47.         }
    48.         if (SceneManager.GetActiveScene() == SceneManager.GetSceneByName("start_area 2"))
    49.         {
    50.             allowCombat = false;
    51.             allowJump = true;
    52.         }
    53.         if (SceneManager.GetActiveScene() == SceneManager.GetSceneByName("level 1"))
    54.         {
    55.             allowCombat = true;
    56.             allowJump = true;
    57.         }
    58.     }
    59.  
    60.     void Update()
    61.     {
    62.         if (knockBackCounter <= 0 && canMove)
    63.         {
    64.             float moveHorizontal = Input.GetAxis("Horizontal");
    65.             float moveVertical = Input.GetAxis("Vertical");
    66.             moveDirection = new Vector2(moveHorizontal * moveSpeed, moveDirection.y);
    67.             extraDirections = new Vector2(moveVertical * moveSpeed, extraDirections.y);
    68.  
    69.             if (moveHorizontal > 0)
    70.             {
    71.                 transform.eulerAngles = new Vector2(0, 90);
    72.             }
    73.             else if (moveHorizontal < 0)
    74.             {
    75.                 transform.eulerAngles = new Vector2(0, -90);
    76.             }
    77.             //To possibly prevent diagonal movement with some control setups, try adding 'else if'
    78.             else if (SceneManager.GetActiveScene() == SceneManager.GetSceneByName("hut_interior"))
    79.             {
    80.                 if (moveVertical > 0)
    81.                 {
    82.                     transform.eulerAngles = new Vector2(0, 0);
    83.                 }
    84.                 else if (NPC.charactersTalking)
    85.                 {
    86.                     canMove = false;
    87.                     anim.SetFloat("Speed", 0F);
    88.                 }
    89.                 //Use this to make the character face towards the camera.
    90.                 /*else if (moveVertical < 0)
    91.                 {
    92.                     transform.eulerAngles = new Vector3(0, 180);
    93.                 }*/
    94.             }
    95.             if (controller.isGrounded)
    96.             {
    97.                 if (allowJump)
    98.                 {
    99.                     moveDirection.y = -1f;
    100.                     //GetKeyDown will require the player to press the button each time they want to jump. GetKey will allow the player to spam the jump button if they keep pressing it down.
    101.                     if (Input.GetKeyDown(KeyCode.KeypadPlus) || Input.GetKeyDown("joystick button 1"))
    102.                     {
    103.                         moveDirection.y = jumpForce;
    104.                         jumped = true;
    105.                     }
    106.                     else if (!Input.GetKeyDown(KeyCode.KeypadPlus) || !Input.GetKeyDown("joystick button 1"))
    107.                     {
    108.                         jumped = false;
    109.                     }
    110.                 }
    111.  
    112.                 if (allowCombat)
    113.                 {
    114.                     if (Input.GetKey(KeyCode.Space) || Input.GetKey("joystick button 7"))
    115.                     {
    116.                         attack = true;
    117.                         playerRenderer.material = textureChange;
    118.                     }
    119.                     else if (!Input.GetKey(KeyCode.Space) || !Input.GetKey("joystick button 7"))
    120.                     {
    121.                         attack = false;
    122.                         playerRenderer.material = textureDefault;
    123.                     }
    124.                 }
    125.                 else if (!allowCombat)
    126.                 {
    127.                     attack = false;
    128.                     playerRenderer.material = textureDefault;
    129.                 }
    130.  
    131.                 if (allowInteract)
    132.                 {
    133.                     if (SceneManagement.xbox360Controller == 1)
    134.                     {
    135.                         if (Input.GetKeyDown("joystick button 2"))
    136.                         {
    137.                             interact = true;
    138.                         }
    139.                     }
    140.                     else if (SceneManagement.ps4Controller == 1)
    141.                     {
    142.                         if (Input.GetKeyDown("joystick button 0"))
    143.                         {
    144.                             interact = true;
    145.                         }
    146.                     }
    147.                     else
    148.                     {
    149.                         interact = true;
    150.                     }
    151.                 }
    152.             }
    153.         }
    154.         else
    155.         {
    156.             knockBackCounter -= Time.deltaTime;
    157.         }
    158.  
    159.         moveDirection.y = moveDirection.y + (Physics.gravity.y * gravityScale * Time.deltaTime);
    160.         controller.Move(moveDirection * Time.deltaTime);
    161.  
    162.         anim.SetBool("isGrounded", controller.isGrounded);
    163.         anim.SetFloat("Speed", Mathf.Abs(Input.GetAxis("Horizontal")));
    164.  
    165.         if (interact)
    166.         {
    167.             if (Input.GetKeyDown(KeyCode.Return))
    168.             {
    169.                 anim.SetBool("Interact", controller.isGrounded);
    170.                 FindObjectOfType<Pickup>().ObjectActivation();
    171.                 interact = false;
    172.                 allowInteract = false;
    173.             }
    174.         }
    175.         if (attack)
    176.         {
    177.             anim.SetTrigger("Attack");
    178.         }
    179.     }
    180.  
    181.     public void Knockback(Vector3 direction)
    182.     {
    183.         knockBackCounter = knockBackTime;
    184.  
    185.         moveDirection = direction * knockBackForce;
    186.         moveDirection.y = knockBackForce;
    187.     }
    188. }
     
  2. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,847
    You've got this canMove bool you are checking, but you are doing controller.Move outside of that. If all your character movement actually occurs with that controller.Move on line 160, then I'd only call that if canMove is true. Or maybe I'm misunderstanding?
     
  3. DustyShinigami

    DustyShinigami

    Joined:
    Jan 5, 2018
    Posts:
    529
    Nicely spotted with the controller.Move; I totally forgot about that. However, I'm still not sure how to get this right. I've added the controller.Move where all the controls are under knockBackCounter <= 0 && canMove, but I'm not sure where I should disable it. I've tried a few places. I've also set controller.Move(new Vector3(0, 0, 0)); but that just makes my character jump up and down on the spot.
     
  4. DustyShinigami

    DustyShinigami

    Joined:
    Jan 5, 2018
    Posts:
    529
    Anyone? I tried adding an isIdle bool in the Animator as a condition to use for when every movement transitions back to my Idle animation, but it isn't working. If I try and define what it is in the script (controller.isIdle) it just gives me a red squiggly line under isIdle. And yet my isGrounded works fine.
    I can stop the Animator altogether when talking to an NPC by using controller.enabled = false, but ideally, I'd like to keep the player's idle animation playing.
     
  5. JasonDN

    JasonDN

    Joined:
    Mar 11, 2013
    Posts:
    35
    Just an idea, didn't look at your script in too much detail, and even if I did I'm quite the newb, but couldn't you maybe just disable the CharacterController when you don't want the player moving at all?

    Edit: Whoops, didn't see your last comment, I guess you already thought of that.
     
  6. Doug_B

    Doug_B

    Joined:
    Jun 4, 2017
    Posts:
    1,596
    I guess the first thing to establish is the source of the movement. By that, I mean is the movement a result of some of your own code changing the
    transform.position
    , or, is it movement being controlled by an animator?

    You mention that the player "moves on the spot" and also that you want to "keep the player's idle animation playing". The latter is a case of the player moving on the spot. :) Can you explain a little more what this unwanted movement is exactly.
     
  7. DustyShinigami

    DustyShinigami

    Joined:
    Jan 5, 2018
    Posts:
    529
    When I say the player moves on the spot, I mean their walk animation plays if you press left/right, but they walk on the spot. :) If you look at the script I shared in the first post, I believe the source of movement is through the CharacterController and a Vector3.
     
  8. Doug_B

    Doug_B

    Joined:
    Jun 4, 2017
    Posts:
    1,596
    In that case, presumably the animator state machine is set to go idle if the speed is below a minimum threshold? If so, then this line seems a potential candidate as the culprit:
    anim.SetFloat("Speed", Mathf.Abs(Input.GetAxis("Horizontal")));
    because there is no guard there for "not currently meeting NPC".

    This is basically the same point as Joe-Censored made above. It looks like you want to handle the movement according to
    canMove
    .

    I wonder if it may help if you code were structured something more like this? :
    Code (CSharp):
    1. public class PlayerController : MonoBehaviour
    2. {
    3.     /*
    4.      * === Here we have our public methods (no variables) that constitute our interface ===
    5.      */
    6.  
    7.     public void Knockback(Vector2 direction)
    8.     {
    9.         myKnockBackCounter = myKnockBackTime;
    10.         myKnockBack = direction * myKnockBackForce;
    11.     }
    12.  
    13.     public bool CanMove
    14.     {
    15.         set
    16.         {
    17.             myCanMove = value;
    18.  
    19.             if(!myCanMove)
    20.             {
    21.                 myAnim.SetFloat(ourSpeed, 0f);
    22.             }
    23.         }
    24.     }
    25.  
    26.     /*
    27.      * === Here we have our private methods (and variables) ===
    28.      */
    29.  
    30.     void Start()
    31.     {
    32.         Cursor.visible = false;
    33.         myCanMove = true;
    34.         myController = GetComponent<CharacterController>();
    35.     }
    36.  
    37.     void Update()
    38.     {
    39.         Vector2 thisMove = Vector2.zero;
    40.  
    41.         if (myKnockBackCounter > 0)
    42.         {
    43.             myKnockBackCounter -= Time.deltaTime;
    44.             thisMove = myKnockBack * Time.deltaTime;
    45.         }
    46.         else if(myCanMove)
    47.         {   // Here we are neither knocked back nor immobilised.
    48.             thisMove.x = Input.GetAxis(ourAxisX);
    49.             thisMove.y = Input.GetAxis(ourAxisY);
    50.  
    51.             // ... other movement related stuff.
    52.         }
    53.  
    54.         myAnim.SetBool("isGrounded", myController.isGrounded);
    55.         myController.Move(thisMove);
    56.     }
    57.  
    58.     static readonly string ourSpeed = "Speed";
    59.     static readonly string ourAxisX = "Horizontal";
    60.     static readonly string ourAxisY = "Vertical";
    61.     [SerializeField] [Range(0.3f, 1f)] float myKnockBackTime;
    62.     [SerializeField] [Range(0.5f, 5f)] float myKnockBackForce;
    63.     Animator myAnim;
    64.     CharacterController myController;
    65.     Vector2 myKnockBack;
    66.     float myKnockBackCounter;
    67.     bool myCanMove;
    68. }
     
  9. DustyShinigami

    DustyShinigami

    Joined:
    Jan 5, 2018
    Posts:
    529
    Thanks for trying to help, but inputting all of that is causing countless issues and 'object reference not set to an instance of an object' errors. It's too much to get my head around. :-\
     
  10. Doug_B

    Doug_B

    Joined:
    Jun 4, 2017
    Posts:
    1,596
    Apologies, it was not intended to simply replace what you had- it would cause the issues you mention. Really the main point was to keep as little public as possible to restrict and control how the internals of the class can be affected from the outside.

    Ok, so to try and keep with the original code as you had it above, I'll hazard a guess based on what you previously mentioned, you could try changing line 163 from
    anim.SetFloat("Speed", Mathf.Abs(Input.GetAxis("Horizontal")));

    to
    Code (CSharp):
    1. anim.SetFloat("Speed",
    2. !canMove
    3. ? 0f
    4. : Mathf.Abs(Input.GetAxis("Horizontal")));
    This says, "if I can't move, then set the 'Speed' to zero, otherwise use the horizontal input value". Does that fix it?

    Incidentally, what methods are you currently using to track down faults? Are you comfortable with debug logging and using a debugger? They will prove themselves to be invaluable friends. :)
     
    DustyShinigami likes this.
  11. DustyShinigami

    DustyShinigami

    Joined:
    Jan 5, 2018
    Posts:
    529
    That's okay. :)

    I've never seen that structure before. I wasn't sure if that was how you were supposed to type it out or not. We're half-way there at least. :D My character's idle animation plays when talking to the NPC, but can't be moved. The issue now is giving movement back to the player once the talking is done. I have this...

    Code (CSharp):
    1. if (NPC.charactersTalking)
    2.             {
    3.                 canMove = false;
    4.             }
    5.             else
    6.             {
    7.                 canMove = true;
    8.             }
    ...and within my NPC script, I have charactersTalking = true;. But once the text box/dialogue has been disabled after pressing Return, charactersTalking = false; isn't giving me back player movement. :-\

    As for debugging, I'm not 100% confident, no. I occasionally use debug logging to see if parts of the code are being read, but I've not had much, if any, experience with a debugger.
     
  12. Doug_B

    Doug_B

    Joined:
    Jun 4, 2017
    Posts:
    1,596
    There are two possibilities here - (1) this is setting a variable value, or, (2) this is setting a property. I can't tell which it is without seeing the code. So let's look at them in turn :
    1. As this is only setting the value to false, it is therefore completely independent of the checking code you just posted. That means that something else will have to call the
      if (NPC.charactersTalking)
      code.
    2. As this is a method call, then that could call the checking code
      if (NPC.charactersTalking)
      .
    Either way, something has to link the setting of the
    charactersTalking = false
    to the checking code that sets
    canMove
    .

    There are many tricks and tips that can be applied when debugging. Debug logging (for example,
    Debug.Log("canMove is " + (canMove ? "true" : "false"));
    ) can prove helpful.

    However, a good debugger is just unspeakably useful. If you are on Windows, I would highly recommend that you install Visual Studio (community edition is free). Spend a little time familiarising yourself with it. The dividends from that time spent will be manifold. :)
     
  13. DustyShinigami

    DustyShinigami

    Joined:
    Jan 5, 2018
    Posts:
    529
    This is the code in my NPC script:

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.SceneManagement;
    5.  
    6. public class NPC : MonoBehaviour
    7. {
    8.     public GameObject[] buttonPrompts;
    9.     public GameObject[] dialogueBoxes;
    10.     public bool characterVicinity = false;
    11.     public static bool charactersTalking = false;
    12.     //public TypeWriterText typeWriter;
    13.  
    14.     private int xbox360Controller = 0;
    15.     private int ps4Controller = 0;
    16.  
    17.     void Start()
    18.     {
    19.         //PlayerController thePlayer = GetComponent<PlayerController>();
    20.         //typeWriter = FindObjectOfType<TypeWriterText>();
    21.     }
    22.  
    23.     public void OnTriggerEnter(Collider other)
    24.     {
    25.         if (other.gameObject.CompareTag ("Player"))
    26.         {
    27.             characterVicinity = true;
    28.             ControllerDetection();
    29.             if (ps4Controller == 1)
    30.             {
    31.                 PS4Prompts();
    32.             }
    33.             else if (xbox360Controller == 1)
    34.             {
    35.                 Xbox360Prompts();
    36.             }
    37.             else
    38.             {
    39.                 PCPrompts();
    40.             }
    41.         }
    42.     }
    43.  
    44.     public void OnTriggerExit(Collider other)
    45.     {
    46.         characterVicinity = false;
    47.     }
    48.  
    49.     public void Update()
    50.     {
    51.         if (characterVicinity)
    52.         {
    53.             if (xbox360Controller == 1)
    54.             {
    55.                 if (Input.GetKeyDown("joystick button 2"))
    56.                 {
    57.                     charactersTalking = true;
    58.                 }
    59.             }
    60.             else if (ps4Controller == 1)
    61.             {
    62.                 if (Input.GetKeyDown("joystick button 0"))
    63.                 {
    64.                     charactersTalking = true;
    65.                 }
    66.             }
    67.             *** else
    68.  
    69.             {
    70.  
    71.                 if (Input.GetKeyDown(KeyCode.Return))
    72.  
    73.                 {
    74.  
    75.                     charactersTalking = true;
    76.  
    77.                     DialogueBoxes();
    78.  
    79.                     if (buttonPrompts[3].activeSelf)
    80.  
    81.                     {
    82.  
    83.                         if (Input.GetKeyDown("joystick button 2") || Input.GetKeyDown("joystick button 0") || Input.GetKeyDown(KeyCode.Return))
    84.  
    85.                         {
    86.  
    87.                             dialogueBoxes[0].SetActive(false);
    88.  
    89.                             //charactersTalking = false;
    90.  
    91.                             //DialogueBoxes();
    92.  
    93.                             //buttonPrompts[3].SetActive(false);
    94.  
    95.                             //dialogueBoxes[0].SetActive(false);
    96.  
    97.                             //dialogueBoxes[1].SetActive(true);
    98.  
    99.                         }
    100.  
    101.                     }
    102.  
    103.                 }
    104.  
    105.             }
    106.  
    107.         }
    108.  
    109.     }
    110.  
    111.  
    112.  
    113.     public void DialogueBoxes()
    114.  
    115.     {
    116.  
    117.         if (!dialogueBoxes[0].activeSelf)
    118.  
    119.         {
    120.  
    121.             dialogueBoxes[0].SetActive(true);
    122.  
    123.             PCPrompts();
    124.  
    125.         }
    126.  
    127.         /*else if (!dialogueBoxes[1].activeSelf)
    128.  
    129.         {
    130.  
    131.             buttonPrompts[3].SetActive(false);
    132.  
    133.             dialogueBoxes[1].SetActive(true);
    134.  
    135.             PCPrompts();
    136.  
    137.         }*/
    138.  
    139.     }
    140.  
    141.  
    142.  
    143.     public void Timer()
    144.  
    145.     {
    146.  
    147.         if (!buttonPrompts[3].activeSelf)
    148.  
    149.         {
    150.  
    151.             buttonPrompts[3].SetActive(true);
    152.  
    153.         }
    154.  
    155.         else
    156.  
    157.         {
    158.  
    159.             buttonPrompts[3].SetActive(false);
    160.  
    161.         }
    162.  
    163.     }
    164.  
    165.  
    166.  
    167.     public void Hide()
    168.  
    169.     {
    170.  
    171.         buttonPrompts[0].SetActive(false);
    172.  
    173.         buttonPrompts[1].SetActive(false);
    174.  
    175.         buttonPrompts[2].SetActive(false);
    176.  
    177.     }
    178.  
    179.     public void Xbox360Prompts()
    180.     {
    181.         buttonPrompts[1].SetActive(true);
    182.         Invoke("Hide", 3f);
    183.     }
    184.  
    185.     public void PS4Prompts()
    186.     {
    187.         buttonPrompts[2].SetActive(true);
    188.         Invoke("Hide", 3f);
    189.     }
    190.  
    191.    public void PCPrompts()
    192.  
    193.     {
    194.  
    195.         buttonPrompts[0].SetActive(true);
    196.  
    197.         Invoke("Hide", 3f);
    198.  
    199.         if (charactersTalking)
    200.  
    201.         {
    202.  
    203.             //Turn off the button prompt completely whilst the player is talking
    204.  
    205.             buttonPrompts[0].SetActive(false);
    206.  
    207.             if (dialogueBoxes[0].activeSelf)
    208.  
    209.             {
    210.  
    211.                 //Timer until a button prompt appears to skip to the next dialogue box
    212.  
    213.                 Invoke("Timer", 3f);
    214.  
    215.             }
    216.  
    217.         }
    218.  
    219.     } ***
    220.  
    221.     public void ControllerDetection()
    222.     {
    223.         string[] names = Input.GetJoystickNames();
    224.         for (int x = 0; x < names.Length; x++)
    225.         {
    226.             //print(names[x].Length);
    227.             if (names[x].Length == 19)
    228.             {
    229.                 //print("PS4 CONTROLLER IS CONNECTED");
    230.                 ps4Controller = 1;
    231.                 xbox360Controller = 0;
    232.                 if (ps4Controller == 1)
    233.                 {
    234.                     //Debug.Log("PS4 controller detected");
    235.                 }
    236.             }
    237.             else if (names[x].Length == 33)
    238.             {
    239.                 //print("XBOX 360 CONTROLLER IS CONNECTED");
    240.                 ps4Controller = 0;
    241.                 xbox360Controller = 1;
    242.                 if (xbox360Controller == 1)
    243.                 {
    244.                     //Debug.Log("Xbox 360 controller detected");
    245.                 }
    246.             }
    247.             else
    248.             {
    249.                 ps4Controller = 0;
    250.                 xbox360Controller = 0;
    251.             }
    252.  
    253.             if (xbox360Controller == 0 && ps4Controller == 0)
    254.             {
    255.                 //Debug.Log("No controllers detected");
    256.             }
    257.         }
    258.     }
    259. }
    I did try making the parts I'm working on in bold, but it's not showing up. :-\ So it's from and to the three stars. I'm trying to set up dialogue boxes when the NPC talks to the player. The first pops up, comes up with a button prompt to continue and then the box disappears. I'm struggling to activate the next box, get a button prompt, press it, and then the conversation ends. But for testing purposes I'm trying to end the conversation after pressing the appropriate button after the first box.

    I have played around a bit with the Debugger, but not enough to be proficient with it and understand how it works completely. I will try and get into a habit of using it from now on.
     
    Last edited: May 18, 2019
  14. DustyShinigami

    DustyShinigami

    Joined:
    Jan 5, 2018
    Posts:
    529
    Also, is...
    1. anim.SetFloat("Speed",
    2. !canMove
    3. ? 0f
    4. : Mathf.Abs(Input.GetAxis("Horizontal")))
    ...just another fancy way of using an 'if' statement?
     
  15. DustyShinigami

    DustyShinigami

    Joined:
    Jan 5, 2018
    Posts:
    529
    And I don't really 'get' the debugger. I set a breakpoint at the part I don't think is working - charactersTalking = false; but that's where it stops at. I already know it doesn't work correctly, but it doesn't exactly give me any information if I continue after that. I don't know what it's doing from there.
     
  16. Dextozz

    Dextozz

    Joined:
    Apr 8, 2018
    Posts:
    493
    Don't continue. Use step over and step into. Please do more research on this topic before giving up and asking here.
     
  17. Doug_B

    Doug_B

    Joined:
    Jun 4, 2017
    Posts:
    1,596
    Yes, exactly that. So
    A ? B : C
    is the same as "if A is true, then use B else use C".

    If this is in Visual Studio :
    • F11 will step either down into functions (but not into properties and operators by default, although this can be changed in the options) or to the next line.
    • F10 will step to the next line (it will not step down into a function call like F11 does).
    • F5 will continue running at full speed until the next breakpoint.
    So, for the most part, you may want to be stepping line by line using F10 and F11 accordingly. With each step you have the opportunity to ask yourself "did that go to the line I was expecting?". Also you can inspect the contents of variables- do they contain the values expected at that point?

    There is one thing that stands out in that section:
    GetKeyDown
    only returns true in the same frame as the action happens. So to have nested checks means that both keys have to be pressed in exactly the same frame. I suspect that may not be what you intended?
     
  18. DustyShinigami

    DustyShinigami

    Joined:
    Jan 5, 2018
    Posts:
    529
    I sort of get what you mean and sort of don't. :p I know I've had problems before with key presses and actions happening at the same time in the Update function. I'm not sure what you mean by both keys have to be pressed in exactly the same frame. So far I have one button prompt to talk to the character, which then turns off/false when I press Enter, the first text box comes up, a button prompt appears after 3 seconds, I press enter and it all disappears. I've still yet to get the second box to appear and then its button prompt. Unless you were referring to GetKeyDown preventing that from happening properly...?
     
  19. Doug_B

    Doug_B

    Joined:
    Jun 4, 2017
    Posts:
    1,596
    In post #13, line 71 says
    if (Input.GetKeyDown(KeyCode.Return))
    and, within that scope, line 83 then checks (in the same frame)
    if (Input.GetKeyDown .....
    .

    This means that both the return key have to be pressed down and one of the joystick buttons have to be pressed down. Both in the same frame. For the avoidance of doubt, pressed down means going from not-pressed-down to being-pressed-down. This is not the same as being held down. Which is why I say they are unlikely to occur at the same instant in time.

    ... oh, right ... just scrolled to the end of line 83 and realised it also has
    || Input.GetKeyDown(KeyCode.Return)
    which, given line 71, means that condition will always be evaluated to true.
     
  20. DustyShinigami

    DustyShinigami

    Joined:
    Jan 5, 2018
    Posts:
    529
    Should I change them to GetKey instead?
     
  21. Doug_B

    Doug_B

    Joined:
    Jun 4, 2017
    Posts:
    1,596
    That very much depends on how the code is intended to work. From looking at the code, I suspect that you do want a
    GetKeyDown
    , certainly for the outer test case (line 71) anyway. If the inner test case (line 83) is necessary, then that one should probably be a
    GetKey 
    check. That way, the appropriate joystick button just has to be already held down at the point the
    Return
    key is pressed.

    So, the way the code above is written, line 87 will be reached when
    Return
    is pressed because the inner check (line 83) will always be true with the "OR is 'return' pressed" part at the end. If that inner
    Return
    check is removed, however, the odds of reaching line 87 will be rather slight (without the change to use
    GetKey
    on line 83).
     
  22. DustyShinigami

    DustyShinigami

    Joined:
    Jan 5, 2018
    Posts:
    529
    Okay, this is starting to confuse me now.
    :-S
     
  23. Doug_B

    Doug_B

    Joined:
    Jun 4, 2017
    Posts:
    1,596
    Don't get disheartened. This happens to everyone. And even if you become seasoned, it will still continue to happen! :)

    Have you tried following a tutorial on this kind of thing to get some pointers. Something like this perhaps?
     
    DustyShinigami likes this.
  24. DustyShinigami

    DustyShinigami

    Joined:
    Jan 5, 2018
    Posts:
    529
    I did do a dialogue system with Adventure Creator, but no scripting was involved. I’ll give that video a watch when I get the chance though. Thanks. :) Do you think the way I’ve set up the dialogue system is affecting the player getting their animation back? Could do with getting that small bug sorted first...
     
  25. Doug_B

    Doug_B

    Joined:
    Jun 4, 2017
    Posts:
    1,596
    I wouldn't put it like that. It seems to me that the
    if (NPC.charactersTalking)
    from above is not being called after
    NPC.charactersTalking
    is set to false. If that is indeed the case, then it is a straightforward bug in its own right. The dialog system could be set up a hundred different ways, but if none of them call the "if" I just mentioned, then the bug would still present itself.

    First, try setting a breakpoint on both the
    charactersTalking = false
    and the
    if (NPC.charactersTalking)
    lines. Now run it under the debugger. After hitting the first breakpoint, does the second breakpoint subsequently get hit? If not, that would seem to be the problem. You would need to find a way to hook the two things together. Maybe take a look again at my comment at the start of message #12 above?
     
  26. DustyShinigami

    DustyShinigami

    Joined:
    Jan 5, 2018
    Posts:
    529
    The first if (NPC.charactersTalking) you mentioned... are you referring to the one on line 75? From what I tested yesterday, when I comment it out, the player character can still move around when the characters talk.
     
  27. DustyShinigami

    DustyShinigami

    Joined:
    Jan 5, 2018
    Posts:
    529
    While that tutorial of Brackey's is useful, I'm finding it difficult to blend his methods together with the setup I currently have. :-\
     
  28. Doug_B

    Doug_B

    Joined:
    Jun 4, 2017
    Posts:
    1,596
    In truth, I am not completely sure that I have a full picture of all your code and how it is structured. Rather I am trying to work backwards from the observed problem to a possible solution. Here is my understanding of the situation :
    1. Player meets NPC -
      charactersTalking
      is set to true.
    2. As a direct result of point 2, the Player is immobilized during the conversation (with
      canMove
      set to false).
    3. The conversation between Player and NPC ends.
    4. charactersTalking
      is set to false.
    5. <Something here>.
    6. canMove
      needs to be set back to true to allow the player to move again.
    As I understand it, points 1 to 4 happen but point 6 does not. Hence, it means that something needs to be done in step 5 to force step 6 to happen after step 4 happens. That is the point I am making.
     
  29. DustyShinigami

    DustyShinigami

    Joined:
    Jan 5, 2018
    Posts:
    529
    If you want I could upload my source files via GitHub, though the last time I got a programmer to look at it, the game didn't load up properly. :-\ Using the debugger, whenever I set a breakpoint at canMove = true; and hit Play, it doesn't and that line immediately goes yellow. So I'm guessing that means it doesn't work...?

    I've also restructured my scripts a bit as well.

    This is the PlayerController:

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.SceneManagement;
    5.  
    6. public class PlayerController : MonoBehaviour
    7. {
    8.     public Animator anim;
    9.     public float moveSpeed;
    10.     public float jumpForce;
    11.     public bool jumped;
    12.     public bool attack;
    13.     public static bool interact = false;
    14.     public static bool allowInteract = false;
    15.     public float gravityScale;
    16.     public float knockBackForce;
    17.     public float knockBackTime;
    18.     public float invincibilityLength;
    19.     public Renderer playerRenderer;
    20.     public Material textureChange;
    21.     public Material textureDefault;
    22.     public bool allowCombat;
    23.     public bool allowJump;
    24.     public bool notDestroyed;
    25.     public bool canMove;
    26.  
    27.     private Vector3 moveDirection;
    28.     private Vector3 extraDirections;
    29.     private float knockBackCounter;
    30.     private float invincibilityCounter;
    31.     private CharacterController controller;
    32.  
    33.     void Start()
    34.     {
    35.         Cursor.visible = false;
    36.         controller = GetComponent<CharacterController>();
    37.         canMove = true;
    38.         if (SceneManager.GetActiveScene() == SceneManager.GetSceneByName("start_area"))
    39.         {
    40.             allowCombat = false;
    41.             allowJump = true;
    42.         }
    43.         if (SceneManager.GetActiveScene() == SceneManager.GetSceneByName("hut_interior"))
    44.         {
    45.             allowCombat = false;
    46.             allowJump = false;
    47.         }
    48.         if (SceneManager.GetActiveScene() == SceneManager.GetSceneByName("start_area 2"))
    49.         {
    50.             allowCombat = false;
    51.             allowJump = true;
    52.         }
    53.         if (SceneManager.GetActiveScene() == SceneManager.GetSceneByName("level 1"))
    54.         {
    55.             allowCombat = true;
    56.             allowJump = true;
    57.         }
    58.     }
    59.  
    60.     void Update()
    61.     {
    62.         if (knockBackCounter <= 0 && canMove)
    63.         {
    64.             float moveHorizontal = Input.GetAxis("Horizontal");
    65.             float moveVertical = Input.GetAxis("Vertical");
    66.             moveDirection = new Vector2(moveHorizontal * moveSpeed, moveDirection.y);
    67.             extraDirections = new Vector2(moveVertical * moveSpeed, extraDirections.y);
    68.             controller.Move(moveDirection * Time.deltaTime);
    69.  
    70.             if (moveHorizontal > 0)
    71.             {
    72.                 transform.eulerAngles = new Vector2(0, 90);
    73.             }
    74.             else if (moveHorizontal < 0)
    75.             {
    76.                 transform.eulerAngles = new Vector2(0, -90);
    77.             }
    78.             //To possibly prevent diagonal movement with some control setups, try adding 'else if'
    79.             else if (SceneManager.GetActiveScene() == SceneManager.GetSceneByName("hut_interior"))
    80.             {
    81.                 if (moveVertical > 0)
    82.                 {
    83.                     transform.eulerAngles = new Vector2(0, 0);
    84.                 }
    85.                 //Use this to make the character face towards the camera.
    86.                 /*else if (moveVertical < 0)
    87.                 {
    88.                     transform.eulerAngles = new Vector3(0, 180);
    89.                 }*/
    90.             }
    91.             if (InteractionController.charactersTalking)
    92.             {
    93.                 canMove = false;
    94.             }
    95.             else
    96.             {
    97.                 canMove = true;
    98.             }
    99.  
    100.             if (controller.isGrounded)
    101.             {
    102.                 if (allowJump)
    103.                 {
    104.                     moveDirection.y = -1f;
    105.                     //GetKeyDown will require the player to press the button each time they want to jump. GetKey will allow the player to spam the jump button if they keep pressing it down.
    106.                     if (Input.GetKeyDown(KeyCode.KeypadPlus) || Input.GetKeyDown("joystick button 1"))
    107.                     {
    108.                         moveDirection.y = jumpForce;
    109.                         jumped = true;
    110.                     }
    111.                     else if (!Input.GetKeyDown(KeyCode.KeypadPlus) || !Input.GetKeyDown("joystick button 1"))
    112.                     {
    113.                         jumped = false;
    114.                     }
    115.                 }
    116.  
    117.                 if (allowCombat)
    118.                 {
    119.                     if (Input.GetKey(KeyCode.Space) || Input.GetKey("joystick button 7"))
    120.                     {
    121.                         attack = true;
    122.                         playerRenderer.material = textureChange;
    123.                     }
    124.                     else if (!Input.GetKey(KeyCode.Space) || !Input.GetKey("joystick button 7"))
    125.                     {
    126.                         attack = false;
    127.                         playerRenderer.material = textureDefault;
    128.                     }
    129.                 }
    130.                 else if (!allowCombat)
    131.                 {
    132.                     attack = false;
    133.                     playerRenderer.material = textureDefault;
    134.                 }
    135.  
    136.                 if (allowInteract)
    137.                 {
    138.                     if (SceneManagement.xbox360Controller == 1)
    139.                     {
    140.                         if (Input.GetKeyDown("joystick button 2"))
    141.                         {
    142.                             interact = true;
    143.                         }
    144.                     }
    145.                     else if (SceneManagement.ps4Controller == 1)
    146.                     {
    147.                         if (Input.GetKeyDown("joystick button 0"))
    148.                         {
    149.                             interact = true;
    150.                         }
    151.                     }
    152.                     else
    153.                     {
    154.                         interact = true;
    155.                     }
    156.                 }
    157.             }
    158.         }
    159.         else
    160.         {
    161.             knockBackCounter -= Time.deltaTime;
    162.         }
    163.  
    164.         moveDirection.y = moveDirection.y + (Physics.gravity.y * gravityScale * Time.deltaTime);
    165.  
    166.         anim.SetBool("isGrounded", controller.isGrounded);
    167.         //If the character can't move, then the Speed is set to 0. Otherwise it'll use the horizontal input value.
    168.         anim.SetFloat("Speed",
    169.             !canMove
    170.             ? 0f
    171.             : Mathf.Abs(Input.GetAxis("Horizontal")));
    172.  
    173.         //anim.SetFloat("Speed", Mathf.Abs(Input.GetAxis("Horizontal")));
    174.  
    175.         if (interact)
    176.         {
    177.             if (Input.GetKeyDown(KeyCode.Return))
    178.             {
    179.                 anim.SetBool("Interact", controller.isGrounded);
    180.                 FindObjectOfType<Pickup>().ObjectActivation();
    181.                 interact = false;
    182.                 allowInteract = false;
    183.             }
    184.         }
    185.         if (attack)
    186.         {
    187.             anim.SetTrigger("Attack");
    188.         }
    189.     }
    190.  
    191.     public void Knockback(Vector3 direction)
    192.     {
    193.         knockBackCounter = knockBackTime;
    194.  
    195.         moveDirection = direction * knockBackForce;
    196.         moveDirection.y = knockBackForce;
    197.     }
    198. }
    I've put my character interactions into a script called InteractionController:

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class InteractionController : MonoBehaviour
    6. {
    7.     public GameObject[] buttonPrompts;
    8.     public GameObject[] dialogueBoxes;
    9.     public bool characterVicinity = false;
    10.     public static bool charactersTalking = false;
    11.  
    12.     private int xbox360Controller = 0;
    13.     private int ps4Controller = 0;
    14.  
    15.     void Update()
    16.     {
    17.         if (characterVicinity)
    18.         {
    19.             if (xbox360Controller == 1)
    20.             {
    21.                 if (Input.GetKeyDown("joystick button 2"))
    22.                 {
    23.                     charactersTalking = true;
    24.                 }
    25.             }
    26.             else if (ps4Controller == 1)
    27.             {
    28.                 if (Input.GetKeyDown("joystick button 0"))
    29.                 {
    30.                     charactersTalking = true;
    31.                 }
    32.             }
    33.             else
    34.             {
    35.                 if (Input.GetKeyDown(KeyCode.Return))
    36.                 {
    37.                     charactersTalking = true;
    38.                     DialogueBoxes();
    39.                     if (buttonPrompts[3].activeSelf)
    40.                     {
    41.                         if (Input.GetKeyDown("joystick button 2") || Input.GetKeyDown("joystick button 0") || Input.GetKeyDown(KeyCode.Return))
    42.                         {
    43.                             dialogueBoxes[0].SetActive(false);
    44.                             charactersTalking = false;
    45.                            
    46.                             //DialogueBoxes();
    47.                             //buttonPrompts[3].SetActive(false);
    48.                             //dialogueBoxes[0].SetActive(false);
    49.                             //dialogueBoxes[1].SetActive(true);
    50.                         }
    51.                     }
    52.                 }
    53.             }
    54.         }
    55.     }
    56.  
    57.     public void OnTriggerEnter(Collider other)
    58.     {
    59.         if (other.gameObject.CompareTag("Player"))
    60.         {
    61.             characterVicinity = true;
    62.             ControllerDetection();
    63.             if (ps4Controller == 1)
    64.             {
    65.                 PS4Prompts();
    66.             }
    67.             else if (xbox360Controller == 1)
    68.             {
    69.                 Xbox360Prompts();
    70.             }
    71.             else
    72.             {
    73.                 PCPrompts();
    74.             }
    75.         }
    76.     }
    77.  
    78.     public void OnTriggerExit(Collider other)
    79.     {
    80.         characterVicinity = false;
    81.     }
    82.  
    83.     public void DialogueBoxes()
    84.     {
    85.         if (!dialogueBoxes[0].activeSelf)
    86.         {
    87.             dialogueBoxes[0].SetActive(true);
    88.             PCPrompts();
    89.         }
    90.         /*else if (!dialogueBoxes[1].activeSelf)
    91.         {
    92.             buttonPrompts[3].SetActive(false);
    93.             dialogueBoxes[1].SetActive(true);
    94.             PCPrompts();
    95.         }*/
    96.     }
    97.  
    98.     public void Timer()
    99.     {
    100.         if (!buttonPrompts[3].activeSelf)
    101.         {
    102.             buttonPrompts[3].SetActive(true);
    103.         }
    104.         else
    105.         {
    106.             buttonPrompts[3].SetActive(false);
    107.         }
    108.     }
    109.  
    110.     public void Hide()
    111.     {
    112.         buttonPrompts[0].SetActive(false);
    113.         buttonPrompts[1].SetActive(false);
    114.         buttonPrompts[2].SetActive(false);
    115.     }
    116.  
    117.     public void Xbox360Prompts()
    118.     {
    119.         buttonPrompts[1].SetActive(true);
    120.         Invoke("Hide", 3f);
    121.     }
    122.  
    123.     public void PS4Prompts()
    124.     {
    125.         buttonPrompts[2].SetActive(true);
    126.         Invoke("Hide", 3f);
    127.     }
    128.  
    129.     public void PCPrompts()
    130.     {
    131.         buttonPrompts[0].SetActive(true);
    132.         Invoke("Hide", 3f);
    133.         if (charactersTalking)
    134.         {
    135.             //Turn off the button prompt completely whilst the player is talking
    136.             buttonPrompts[0].SetActive(false);
    137.             if (dialogueBoxes[0].activeSelf)
    138.             {
    139.                 //Timer until a button prompt appears to skip to the next dialogue box
    140.                 Invoke("Timer", 3f);
    141.             }
    142.         }
    143.     }
    144.  
    145.     public void ControllerDetection()
    146.     {
    147.         string[] names = Input.GetJoystickNames();
    148.         for (int x = 0; x < names.Length; x++)
    149.         {
    150.             //print(names[x].Length);
    151.             if (names[x].Length == 19)
    152.             {
    153.                 //print("PS4 CONTROLLER IS CONNECTED");
    154.                 ps4Controller = 1;
    155.                 xbox360Controller = 0;
    156.                 if (ps4Controller == 1)
    157.                 {
    158.                     //Debug.Log("PS4 controller detected");
    159.                 }
    160.             }
    161.             else if (names[x].Length == 33)
    162.             {
    163.                 //print("XBOX 360 CONTROLLER IS CONNECTED");
    164.                 ps4Controller = 0;
    165.                 xbox360Controller = 1;
    166.                 if (xbox360Controller == 1)
    167.                 {
    168.                     //Debug.Log("Xbox 360 controller detected");
    169.                 }
    170.             }
    171.             else
    172.             {
    173.                 ps4Controller = 0;
    174.                 xbox360Controller = 0;
    175.             }
    176.  
    177.             if (xbox360Controller == 0 && ps4Controller == 0)
    178.             {
    179.                 //Debug.Log("No controllers detected");
    180.             }
    181.         }
    182.     }
    183. }
    184.  
    And then I have my NPC one, which I plan to use for the game to control the NPC after they finish talking, walk over to a lever, pull it and walk back again.

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.SceneManagement;
    5.  
    6. public class NPC : MonoBehaviour
    7. {
    8.     public Animator anim;
    9.     public float moveSpeed;
    10.     public bool isWalking;
    11.     public float walkTime;
    12.     public float gravityScale;
    13.     public bool canMove;
    14.     public static bool interact = false;
    15.     public static bool allowInteract = false;
    16.     public GameObject destinationTarget;
    17.     public GameObject startPoint;
    18.     public float targetDistance;
    19.     public float allowedDistance = 5;
    20.     public RaycastHit shot;
    21.  
    22.     private Vector3 moveDirection;
    23.     private Vector3 extraDirections;
    24.     private float walkCounter;
    25.     private int WalkDirection;
    26.     private CharacterController controller;
    27.  
    28.     void Start()
    29.     {
    30.         controller = GetComponent<CharacterController>();
    31.         canMove = false;
    32.         walkCounter = walkTime;
    33.         //MoveDirection();
    34.     }
    35.  
    36.     public void Update()
    37.     {
    38.         if (!canMove)
    39.         {
    40.             isWalking = false;
    41.             anim.SetBool("isGrounded", controller.isGrounded);
    42.             //If the character can't move, then the Speed is set to 0. Otherwise it'll use the horizontal input value.
    43.             anim.SetFloat("Speed",
    44.                 !canMove
    45.                 ? 0f
    46.                 : Mathf.Abs(Input.GetAxis("Horizontal")));
    47.         }
    48.  
    49.         if (canMove)
    50.         {
    51.             float moveHorizontal = Input.GetAxis("Horizontal");
    52.             float moveVertical = Input.GetAxis("Vertical");
    53.             moveDirection = new Vector2(moveHorizontal * moveSpeed, moveDirection.y);
    54.             extraDirections = new Vector2(moveVertical * moveSpeed, extraDirections.y);
    55.             controller.Move(moveDirection * Time.deltaTime);
    56.  
    57.             if (moveHorizontal > 0)
    58.             {
    59.                 transform.eulerAngles = new Vector2(0, 90);
    60.             }
    61.             else if (moveHorizontal < 0)
    62.             {
    63.                 transform.eulerAngles = new Vector2(0, -90);
    64.             }
    65.             if (!InteractionController.charactersTalking)
    66.             {
    67.                 isWalking = true;
    68.                 if (Physics.Raycast(transform.position, transform.TransformDirection(Vector3.forward), out shot))
    69.                 {
    70.                     targetDistance = shot.distance;
    71.                     if (targetDistance >= allowedDistance)
    72.                     {
    73.                         moveSpeed = 0.02f;
    74.                         GetComponent<Animation>().Play("Walk");
    75.                         transform.position = Vector3.MoveTowards(startPoint.transform.position, destinationTarget.transform.position, moveSpeed);
    76.                     }
    77.                     else
    78.                     {
    79.                         moveSpeed = 0;
    80.                         GetComponent<Animation>().Play("Idle");
    81.                     }
    82.                 }
    83.  
    84.                 if (interact)
    85.                 {
    86.                     anim.SetBool("Interact", controller.isGrounded);
    87.                 }
    88.             }
    89.         }
    90.             /*if (isWalking)
    91.             {
    92.                 walkCounter -= Time.deltaTime;
    93.                 if (walkCounter < 0)
    94.                 {
    95.                     isWalking = false;
    96.                 }
    97.                 /*switch (WalkDirection)
    98.                 {
    99.                     case 0:
    100.                         controller.velocity = new Vector2(moveSpeed, 0);
    101.                         break;
    102.  
    103.                     case 1:
    104.                         myRigidbody.velocity = new Vector2(-moveSpeed, 0);
    105.                         break;
    106.                 }
    107.             }
    108.  
    109.     public void MoveDirection()
    110.     {
    111.         WalkDirection = Random.Range(0, 1);
    112.         isWalking = true;
    113.         walkCounter = walkTime;
    114.     }*/
    115.     }
    116. }
     
  30. Doug_B

    Doug_B

    Joined:
    Jun 4, 2017
    Posts:
    1,596
    If you hover your cursor on the yellow break point what does it say? If it says something like "The breakpoint will nol not currently be hit - no corresponding location", then either you have not attached the script to an object, or that object hasn't yet been loaded into the scene.
     
  31. DustyShinigami

    DustyShinigami

    Joined:
    Jan 5, 2018
    Posts:
    529
    I can't for the life of me figure out how to link charactersTalking = false to the code that sets canMove. :-\

    EDIT: It doesn't appear to tell me anything. Just the location of it and its type. But if I set a breakpoint at canMove = false and charactersTalking = false, it will check those in that order. However, if I select canMove = true, which should be the last thing it checks, it tries to check that first.
     
    Last edited: May 19, 2019
  32. DustyShinigami

    DustyShinigami

    Joined:
    Jan 5, 2018
    Posts:
    529
    I think I've got it. :D Instead of setting up canMove = true/false in the PlayerController, I made the variable static and then referenced it in the InteractionController here:

    Code (CSharp):
    1. if (Input.GetKeyDown(KeyCode.Return))
    2.                 {
    3.                     charactersTalking = true;
    4.                     PlayerController.canMove = false;
    5.                     DialogueBoxes();
    6.                     if (buttonPrompts[3].activeSelf)
    7.                     {
    8.                         if (Input.GetKeyDown("joystick button 2") || Input.GetKeyDown("joystick button 0") || Input.GetKeyDown(KeyCode.Return))
    9.                         {
    10.                             dialogueBoxes[0].SetActive(false);
    11.                             charactersTalking = false;
    12.                             PlayerController.canMove = true;
    13.                         }
     
  33. DustyShinigami

    DustyShinigami

    Joined:
    Jan 5, 2018
    Posts:
    529
    I'm still having issues with key presses. I'm trying to follow this tutorial, but the way it's done here isn't working for me. :-\

     
  34. Doug_B

    Doug_B

    Joined:
    Jun 4, 2017
    Posts:
    1,596
    Which bit isn't working the actual handling of key presses or the dialog system itself? Also, how is it going wrong?
     
  35. DustyShinigami

    DustyShinigami

    Joined:
    Jan 5, 2018
    Posts:
    529
    Okay, in the end, I started following this tutorial and I'm happy with the results for the most part. :)


    It was the key presses that weren't working. In the tutorial, activating the text box was done with GetKeyUp and deactivating was GetKeyDown. However, for me, it was conflicting and it either wasn't doing anything or a bit late.