Weird Boolean Issue

Hi,

I am currently coding a game which works like the puck things you find in arcades.

The problem I am havign is that the boolean sometimes registers isMoving and other times does not when the spacebar is pressed.

PlayerController

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerController : MonoBehaviour
{

    private GameObject tempHitVar;

    public PhysicMaterial PuckPhysicsMaterial;

    // Start is called before the first frame update
    void Start()
    {
        tempHitVar = GameObject.FindGameObjectWithTag("PlayerPuck");    
    }

    // Update is called once per frame
    void Update()

    {     
            if(Input.GetMouseButton(0))
            {
                    //Shoot a ray onto the scene at the mouse postiion.
                   Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
                    //Did we hit anything???
                    if(Physics.Raycast(ray, out RaycastHit hit))
                    {
                        //If we hit the player puck.
                        if(hit.collider.tag == "PlayerPuck")
                        {
                           
                            //The player has "picked up" the puck
                           bool isSelected = tempHitVar.GetComponent<PuckController>().isSelected = true;
                           //Set all the box collides to null physics material as while the player is "holding" the puck we dont want it to "bounce" upon dropping it.
                           BoxCollider[] bc = tempHitVar.GetComponents<BoxCollider>();
                            foreach(BoxCollider boxCol in bc)
                            {

                                boxCol.material = null;

                            }

                        }

                    }              
                    //#TODO :  Update the location on the X and Z axis allowing them to drop it in a different location to start the game.
            }

            Rigidbody rb = tempHitVar.transform.gameObject.GetComponent<Rigidbody>();

        

            if(Input.GetMouseButtonUp(0))
            {
                bool unSelected = tempHitVar.gameObject.GetComponent<PuckController>().isSelected = false;
              
            }
            //If the player has pressed the space button and is not currently "holding" the puck.
            if(Input.GetKeyDown(KeyCode.Space) && (tempHitVar.gameObject.GetComponent<PuckController>().isSelected == false))
            {
                //If the puck is moving, we must wait for it to finish.
                if(tempHitVar.gameObject.GetComponent<PuckController>().isMoving == true)
                {
                 
                    Debug.Log("Puck is moving cannot hit again yet....");

                }else{
                   
                        //Add a specified amount of "push" force to the puck.
                        rb.AddForce(Vector3.forward * tempHitVar.gameObject.GetComponent<PuckController>().PushSpeed);
                        // The puck is now moving...
                        tempHitVar.GetComponent<PuckController>().isMoving = true;
                        //Update the box colliders on the puck (I am using 2 box colliders in a cross shape pattern to detect collisions,
                        //There was no cylinder collider and i could not use Gravity with a Mesh Collider.)
                        BoxCollider[] bc = tempHitVar.GetComponents<BoxCollider>();
                            foreach(BoxCollider boxCol in bc)
                            {

                                boxCol.material = PuckPhysicsMaterial;

                            }
                }     
            }

            //if the puck is moving.
            if(tempHitVar.gameObject.GetComponent<PuckController>().isMoving == true)
                {
                    //Disable the aiming tool
                      Transform Aimer = tempHitVar.transform.Find("Aimer");
                        Aimer.gameObject.SetActive(false);
                    //Once the puck has stopped re-enaable the aiming tool to allow the player to aim the firing direction.
                }else if(tempHitVar.gameObject.GetComponent<PuckController>().isMoving == false){

                     Transform Aimer = tempHitVar.transform.Find("Aimer");
                      Aimer.gameObject.SetActive(true);
                }
            //RESET THE PUCKS POSITION AND ROTATION. <<DEMO FUNCTION.
             if(Input.GetKeyDown(KeyCode.B))
                {


                    if(rb.velocity != Vector3.zero)
                   {

                       tempHitVar.gameObject.GetComponent<PuckController>().isMoving = false;
                       rb.velocity = new Vector3(0,0,0);
                        tempHitVar.gameObject.transform.position = new Vector3(0f, 0.05f,-3f);
                         Quaternion myRotation = Quaternion.identity;
                        myRotation.eulerAngles = new Vector3(0,0,0);

                    Debug.Log("RESETTING...");

                   }
                }

                //This controls the "aimer" and allows it to rotate around the position of the puck.
                if(Input.GetKey(KeyCode.N))
                {

                    SpriteRenderer sr = tempHitVar.gameObject.GetComponentInChildren<SpriteRenderer>();
                  
                    sr.transform.RotateAround(tempHitVar.transform.position,Vector3.up, -tempHitVar.gameObject.GetComponent<PuckController>().turnSpeed * Time.deltaTime);
                    //# TO DO : Send the current rotation of the aimer to the puck before firing so we can fire the puck in that direction.
                }

                if(Input.GetKey(KeyCode.M))
                {

                    SpriteRenderer sr = tempHitVar.gameObject.GetComponentInChildren<SpriteRenderer>();
                  
                    sr.transform.RotateAround(tempHitVar.transform.position,Vector3.up, tempHitVar.gameObject.GetComponent<PuckController>().turnSpeed * Time.deltaTime);
              
                }




        }



    }

Then I have this on the actual puck.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PuckController : MonoBehaviour
{

    public float HoldHeight;

    public bool isSelected;

    public float PushSpeed;
   
    public bool isMoving;

    public float turnSpeed;


    // Update is called once per frame
    void Update()
    {

        if(isSelected)
        {           
           
            transform.position = new Vector3(transform.position.x,HoldHeight, transform.position.z);
        }

        Rigidbody rb = transform.GetComponent<Rigidbody>();
        if(rb.velocity == Vector3.zero)
        {
            isMoving = false;
        }

    }
}

If anyone can tell me why the isMoving sometimes triggers and other times it doesn,t, it would be apprecuated!

Many thanks!

To find out what is setting isMoving, add a setter that logs when it is set, and then look at the stack trace.

Note also that the re-set ismoving, you are making an absolute comparison to a three-float Array (velocity == Vector3.Zero), which is bound to no work. Better compare the magnituteSquare to a small value (e.g. 0.001). This may have an Impact on your issue as isMoving may not be reset as intended.

I also recommend you get rid of the many GetComponent<>() invocations and cache the component at Start().This should not be a factor in your current issue.

write it as

public bool isMoving => GetComponent<Rigidbody>().velocity.sqrMagnitude < 0.1f;

and add this to your Update function

if(!isMoving) {
  GetComponent<Rigidbody>().velocity = Vector3.zero;
}

velocity will never be zero for non-kinematic rigidbody. It will be somewhat {0.0000012,0.000000003,0.000000001} for stopped body. To be absolutely correct, you neet to compare velocity magnitude against rigidbody sleep threshold

Ahh thanks so much for the replies!, Glad to know I was on the right lines for a change. :slight_smile:

@csofranz : I was planning to “clean-up” after it,s at least working like removing duplicate and look at how I can reduce the number of calls to GetComponent and I plan to do that, Thanks for the suggestion though!

Just a quick one,

If anyone can tell me how you rotate the actual axis like rotateAround is working fine and rotates around its parent object but even if the arrows are facing the opposite direction the axis do not update.

I am imagining this is easy, I just cant think at the moment…Anyone had like a moment where your brain stops working…

 if(Input.GetKey(KeyCode.N))
                {

                    MeshRenderer sr = tempHitVar.gameObject.GetComponentInChildren<MeshRenderer>();
                    //tempHitVar.transform.Rotate(Vector3.up, tempHitVar.gameObject.GetComponent<PuckController>().turnSpeed * Time.deltaTime);
                    sr.transform.RotateAround(tempHitVar.transform.position,Vector3.up, -tempHitVar.gameObject.GetComponent<PuckController>().turnSpeed * Time.deltaTime);
                    //# TO DO : Send the current rotation of the aimer to the puck before firing so we can fire the puck in that direction.
                }

                if(Input.GetKey(KeyCode.M))
                {

                    MeshRenderer sr = tempHitVar.gameObject.GetComponentInChildren<MeshRenderer>();
                  
                   // sr.transform.RotateAround(tempHitVar.transform.position,Vector3.up, tempHitVar.gameObject.GetComponent<PuckController>().turnSpeed * Time.deltaTime);
                    //sr.transform.Rotate(Vector3.up, tempHitVar.gameObject.GetComponent<PuckController>().turnSpeed * Time.deltaTime);
                    tempHitVar.transform.Translate(new Vector3(5 * Time.deltaTime, 0 ,0));
                }

                if(Input.GetKeyDown(KeyCode.U))
                {


                    Transform aimerTransform = tempHitVar.gameObject.GetComponentInChildren<Transform>();

                    tempHitVar.transform.LookAt(aimerTransform);




                }

I tried a LookAt but that wont work as the axis on the arrows are not updating with the rotatearound function.

Many thanks.

5219198--520091--AxisProblem.JPG

I managed to fix my Axis Rotation issue.

The script below allowed me to rotate the axis as well as the actual object itself.

using UnityEngine;

public class Rotater : MonoBehaviour {

    public float rotationSpeed = 30f;

    // Update is called once per frame
    void Update () {
        RotateAimer ();
    }


    void RotateAimer()
    {

        if (Input.GetKey (KeyCode.A)) {
            rotateLeft ();
        }

        if (Input.GetKey(KeyCode.D)) {
            rotateRight ();
        }
    }

    void rotateLeft()
    {
        float horizontal = Input.GetAxis ("Horizontal") * rotationSpeed * Time.deltaTime;
        transform.Rotate (0, horizontal, 0);

    }

    void rotateRight()
    {
        float horizontal = Input.GetAxis ("Horizontal") * rotationSpeed * Time.deltaTime;
        transform.Rotate (0, horizontal, 0);
    }
}