0
\$\begingroup\$

The first script:

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

public class DetectInteractable : MonoBehaviour
{
    public Camera cam;
    public float distanceToSee;
    public string objectHit;
    public bool interactableObject = false;
    public Transform parentToSearch;
    public static bool detected = false;

    private RaycastHit whatObjectHit;
    private bool clickForDescription = false;
    private int layerMask = 1 << 8;
    private GameObject objectWasHit;

    private void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            clickForDescription = true;

            if (whatObjectHit.collider != null)
                ExecuteActions(whatObjectHit.collider.gameObject);
        }

        Debug.DrawRay(cam.transform.position, cam.transform.forward * distanceToSee, Color.magenta);
        if (Physics.Raycast(cam.transform.position, cam.transform.forward, out whatObjectHit, distanceToSee, layerMask))
        {
            objectWasHit = whatObjectHit.collider.gameObject;
            detected = true;
            objectHit = whatObjectHit.collider.gameObject.name;
            interactableObject = true;
            print("Hit ! " + whatObjectHit.collider.gameObject.name);
        }
        else
        {
            detected = false;
            clickForDescription = false;
            print("Not Hit !");
        }
    }

    private void ExecuteActions(GameObject go)
    {
        ItemAction iaa = go.GetComponent<ItemAction>();

        if (iaa != null)
            iaa.ItemMove();
    }

    private void OnGUI()
    {
        if (clickForDescription == true)
        {
            ProcessOnGUI(parentToSearch);
        }
    }

    void ProcessOnGUI(Transform parent, int level = 0)
    {
        foreach (Transform child in parent)
        {
            if (child.GetComponent<ItemInformation>() != null)
            {
                ItemInformation iteminformation = child.GetComponent<ItemInformation>();
                if (child.name == objectHit)
                {
                    var centeredStyle = GUI.skin.GetStyle("Label");
                    centeredStyle.alignment = TextAnchor.UpperCenter;
                    GUI.Box(new Rect(
                          Screen.width / 2 - 50 + 20 * level, // <== INDENTATION
                          Screen.height / 2 - 25, 100, 50),
                        iteminformation.description, centeredStyle);
                }
            }
            // Process next deeper level
            ProcessOnGUI(child, level + 1);
        }
    }

    public class ViewableObject : MonoBehaviour
    {
        public string displayText;
        public bool isInteractable;
    }
}

In this script inside ExecuteActions I'm calling ItemMove

iaa.ItemMove();

The script ItemAction:

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

public class ItemAction : MonoBehaviour
{
    public virtual void ItemMove()
    {

    }
}

Then the script ItemActions:

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

public class ItemActions : ItemAction
{
    public override void ItemMove()
    {

    }
}

And the script with the action I want to do:

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

public class NaviMove : MonoBehaviour
{
    public GameObject target;
    public ObjectsManipulation om;
    public float moveSpeed = 1f;
    public float maxFallSpeed = 2f;
    public float rotationSpeed = 1f;

    private Rigidbody rigid;
    private bool OnTheGround = false;

    void Awake()
    {
        rigid = GetComponent<Rigidbody>();  //get the rigidbody that attached to the object
    }
    void Start()
    {

    }
    void FixedUpdate()  //physic should be done in FixedUpdate not Update
    {
        if (DetectInteractable.detected == true)
        {
            transform.parent = null;  //disconnect the object for it's parent
            om.stopRotation = true;
        }
        if (om.stopRotation == true)
        {
            if (rigid.velocity.sqrMagnitude > maxFallSpeed) //check if it's falling to fast
            {
                rigid.velocity *= 0.99f; // falling to fast, so reduce speed,  you may want to play around with this number.
            }
            else // if not falling to fast add force to make it fall faster
            {
                rigid.AddForce(Vector3.down * moveSpeed);
            }
        }
    }

    private void OnCollisionEnter(Collision collision)
    {
        OnTheGround = true;
    }

    private void Update()
    {
        if (OnTheGround == true)
        {
            MoveToTarget();
        }
    }

    private void MoveToTarget()
    {
        Vector3 direction = target.transform.position - transform.position;
        Quaternion toRotation = Quaternion.FromToRotation(transform.up, direction);
        transform.rotation = Quaternion.Lerp(transform.rotation, toRotation, rotationSpeed * Time.time);

        transform.position = Vector3.MoveTowards(transform.position, target.transform.position, moveSpeed * Time.deltaTime);
    }
}

Since I'm doing this check:

if (DetectInteractable.detected == true)

Once i'm running the game and there is a detection the object will start moving. But I want that only if I make a mouse left button click and there is also a detection only then move the object.

In the first script I'm doing the mouse left click:

if (Input.GetMouseButtonDown(0))
            {
                clickForDescription = true;

                if (whatObjectHit.collider != null)
                    ExecuteActions(whatObjectHit.collider.gameObject);
            }

The problem:

I'm only checking if detected is true but not if the mouse left button was clicked. But I'm checking the mouse left click in the first script already so I need somehow to do it there using the ItemAction and ItemActions scripts.

I'm doing:

if (Input.GetMouseButtonDown(0))
                {
                    clickForDescription = true;

                    if (whatObjectHit.collider != null)
                        ExecuteActions(whatObjectHit.collider.gameObject);
                }

Somehow I need to call the NaviMove script or to make it start working from inside the script ItemActions I guess.

The NaviMove is attached to a gameobject. The idea is to make the script NaviMove a action when making a detection with specific item.

UPDATE of what I did:

Insidie actions I added a static flag:

public static bool move = false;

    public override void ItemMove()
    {
        move = true;
    }

Then in the NaviMove script I did:

if (DetectInteractable.detected == true && ItemActions.move == true)

Now it's working fine.

The question if using static flags is a right thing to do in this case ? And the way i'm using the Action and Actions script if it's the right way ?

\$\endgroup\$
  • \$\begingroup\$ Updated my question in the bottom with what I did. It's now working but I'm not sure if it's the right way to do it as I did. \$\endgroup\$ – jdoedoe doedoe Mar 10 '18 at 21:47
  • 2
    \$\begingroup\$ The way you done it there is no need for ItemActions. You could have added the "static move" straight into NaviMove or DetectInteractable. ...But there are catches with statics (and reasons for things to not be easy to reach). You can instead search and read about "GetComponent". \$\endgroup\$ – Nikaas Mar 11 '18 at 7:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.