【问题标题】:Enable/Disable one script from another one on specific game object?在特定游戏对象上启用/禁用另一个脚本?
【发布时间】:2021-07-06 16:17:45
【问题描述】:

所以我制作了一个脚本来投射光线并查看鼠标光标是否正在查看一个对象,然后另一个脚本将使用它来打开/关闭该对象上的脚本。第一个脚本正在工作,光线投射一个,但我无法弄清楚如何正确禁用/启用该脚本的大纲脚本。现在,大纲始终处于打开状态。所以基本上,我该如何修复它,使其仅在突出显示时打开? (我也是 stackoverflow 的新手,所以如果格式很奇怪,那就是为什么)

光线投射代码:

public static string selectedObject;
public string internalObject;
public RaycastHit theObject;
public LayerMask layerMask;
public bool rayObjectHit;

void Start()
{

}
void Update()
{
    // Script for highlighting object

    
        Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
        if (Physics.Raycast(ray, out theObject, layerMask))
        {
            selectedObject = theObject.transform.gameObject.name;
            internalObject = theObject.transform.gameObject.name;
        }
    if (Physics.Raycast(ray, out theObject, layerMask) == false)
    {
        selectedObject = GameObject.Find("none").name;
    }
        // Script for clicking on object
        if (Input.GetMouseButtonDown(0))
    {
        if (Physics.Raycast(ray, out theObject, layerMask))
        {
            Debug.Log(theObject.transform.gameObject.name);
        }
        
    }
}

大纲代码:

{
public GameObject selectedObject;
public static string objectSelected;
public bool lookingAtObject = false;
public bool outlineOn;
public static string outlinedObject;

// Start is called before the first frame update
void Start()
{
    selectedObject = GameObject.Find("none");
}

// Update is called once per frame
void Update()
{
        selectedObject = GameObject.Find(CastingToObject.selectedObject);
        lookingAtObject = true;
    if (selectedObject = GameObject.Find("none"))
    {
        lookingAtObject = false;
    }    
    
            
   
    if (lookingAtObject == true)
    {
        selectedObject.GetComponent<GameObject>();
        while (lookingAtObject == true)
        {
            outlineOn = true;
            selectedObject.GetComponent<Outline>().enabled = true;
        }
    }
    if (lookingAtObject == false)
    {
            outlineOn = false;
            selectedObject.GetComponent<Outline>().enabled = false;
    }
}

}

【问题讨论】:

    标签: c# visual-studio unity3d


    【解决方案1】:

    不要进行两次 Raycast!您可以简单地使用else,这意味着没有命中。

    我会做类似的事情

    // Store the current selected outline reference
    Outline currentSelected;
    
    private void Update ()
    {
        var ray = Camera.main.ScreenPointToRay(Input.mousePosition);
    
        // Do they Raycast only ONCE!
        if (Physics.Raycast(ray, out var hit, layerMask))
        {
            // Are we hitting a new object?
            if(!currentSelected || currentSelected.gameObject != hit.gameObject)
            {
                // Was there already something selected?
                // And if so is it a different object?
                if(currentSelected && currentSelected.gameObject != hit.gameObject)
                {
                    currentSelected.enabled = false;
                }
    
                // Did we hit something with an outline?
                if(hit.gameObejct.TryGetComponent<Outline>(out currentSelected))
                {
                    // If so enable it
                    // it is already automatically stored as current selection
                    currentSelected.enabled = true;          
                }
                // otherwise the current selection will be set to null automatically
            }
            // otherwise nothing to do since we still hit the same object
        }
        else // not hitting anything
        {
            // Do we still have something selected?
            if(currentSelected) 
            {
                // Then disable it
                currentSelected.enabled = false;
            }
            // And forget the reference
            currentSelected = null;
        }
    
        // If we have a current selection and click
        if (currentSelected && Input.GetMouseButtonDown(0))
        {
            Debug.Log($"Clicked on {currentSelected.name}", this);    
        }    
    }
    

    【讨论】:

    • 当我将该代码放入脚本时,它只会在“gameObject”上给我错误。修复它的建议是在 ` if (currentSelected && currentSelected.gameObject != hit.gameObject) ` 之后放置一个 else 语句,这甚至不能解决任何问题。有什么帮助吗?
    • 谢谢你!进行两次光线投射有助于稍微清理代码,但我仍然需要更长的时间才能使其正常工作,但我做到了。此外,我确实最终使用了两个脚本,因为我不得不这样做,一个必须在相机上,另一个必须在物体上。我也不能把代码写得太长。
    【解决方案2】:

    我终于成功了!对于以后阅读本文并需要它的任何人,这里是完成的代码。 光线投射脚本:

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    
    public class CastingToObject : MonoBehaviour
    {
    
    public static string selectedObject;
    public string internalObject;
    public RaycastHit theObject;
    public LayerMask layerMask;
    public bool rayObjectHit;
    
    
    void Start()
    {
        internalObject = "null";
    }
    // Store the current selected outline reference
    Outline currentSelected;
    void Update()
    {
        // Script for highlighting object
    
    
        Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
        if (Physics.Raycast(ray, out theObject, layerMask))
        {
            selectedObject = theObject.transform.gameObject.name;
            internalObject = theObject.transform.gameObject.name;
        }
        else
        {
            selectedObject = null;
            internalObject = "null";
        }
            if (selectedObject != null)
        {
            // Script for clicking object
            if (Input.GetMouseButtonDown(0))
            {
                Debug.Log(theObject.transform.gameObject.name);
            }
    
            
        }
        
    }
    }
    

    启用/禁用另一个脚本:

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class SelectedFlash : MonoBehaviour
    {
    public GameObject highlightObject;
    public Outline outlineScript;
    public bool lookingAtObject = false;
    public GameObject noneObject;
    private CastingToObject castingToObjectScript;
    
    
    // Start is called before the first frame update
    void Start()
    {
        noneObject = GameObject.Find("none");
        castingToObjectScript = GetComponent<CastingToObject>();
        lookingAtObject = false;
        outlineScript = GetComponent<Outline>();
    }
    
    // Update is called once per frame
    void Update()
    {
        highlightObject = GameObject.Find(CastingToObject.selectedObject);
            
        if (highlightObject == null) //Nothing selected
        {
            lookingAtObject = false;
            GetComponent<Outline>().enabled = false;
            highlightObject = noneObject;
            
        }
        if (highlightObject != null) //Something selected
        {
            lookingAtObject = true;
            highlightObject.GetComponent<Outline>().enabled = true;
        }
    
    }
    }
    

    【讨论】:

    • 你仍然会更好地使用一个脚本来完成这个.. 在Update 中每帧轮询状态比基于工作事件要糟糕得多。同样使用Find 非常昂贵,对您来说毫无意义...您已经拥有CastingToObject.selectedObject 的引用,那么您为什么要使用昂贵的Find 只是为了选择相同引用或 - 在多个对象的名称相同的不良情况下 - 一个错误的对象...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多