You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity躲桌时Player对象未隐藏问题求助

Unity问题:躲进桌下时Player对象无法隐藏

我正在制作一个支持玩家躲进储物柜和桌子下方的Unity小项目。目前躲进储物柜时Player能正常隐藏,但触发桌子的互动脚本时,Player始终保持显示状态,无法隐藏,多方排查无果,寻求解决办法。

桌子绑定脚本

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

public class TriggerTable : MonoBehaviour
{
    [SerializeField] private bool isHidingTable;
    [SerializeField] private bool canHideTable;
    [SerializeField] private Transform cameraTablePos;
    [SerializeField] private new Transform camera;
    [SerializeField] private GameObject player;
    [SerializeField] private Camera playerCamera;
    [SerializeField] private Camera tableCamera;

    void Start()
    {
        cameraTablePos = GameObject.Find("TablePosition").transform;
        player = GameObject.Find("Player");
        
        playerCamera = GameObject.Find("Main Camera").GetComponent<Camera>();
        tableCamera = GameObject.Find("TableCamera").GetComponent<Camera>();

        playerCamera.enabled = true;
        tableCamera.enabled = false;
        
        tableCamera.transform.SetParent(null);
    }

    void switchToTableCam()
    {
        player.SetActive(false);
        playerCamera.enabled = false;
        tableCamera.enabled = true;
    }

    void switchToPlayerCam()
    {
        player.SetActive(true);
        tableCamera.enabled = false;
        playerCamera.enabled = true;
    }

    private void OnTriggerEnter(Collider collision)
    {
        if (collision.CompareTag("Player"))
        {
            canHideTable = true;
        }
    }

    private void OnTriggerExit(Collider collision)
    {
        if (collision.CompareTag("Player"))
        {
            canHideTable = false;   
        }
    }

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.E) && canHideTable)
        {
            isHidingTable = !isHidingTable;
        }

        if (isHidingTable)
        {
            tableCamera.transform.SetParent(null);
            camera.parent = cameraTablePos;
            camera.position = cameraTablePos.position;
            switchToTableCam();
        }

        else
        {
            switchToPlayerCam();
        }
        
    }
}

储物柜绑定脚本

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

public class TriggerLockerDoor : MonoBehaviour
{
   [SerializeField] private bool isHidingLocker;
   [SerializeField] private bool canHideLocker;
   [SerializeField] private Transform cameraLockerPos;
   [SerializeField] private new Transform camera;
   [SerializeField] private GameObject player;
   [SerializeField] private Camera playerCamera;
   [SerializeField] private Camera lockerCamera;

   void Start()
   {
      cameraLockerPos = GameObject.Find("LockerPosition").transform;
      player = GameObject.Find("Player");
      
      playerCamera = GameObject.Find("Main Camera").GetComponent<Camera>();
      lockerCamera = GameObject.Find("LockerCamera").GetComponent<Camera>();    
      
      playerCamera.enabled = true;
      lockerCamera.enabled = false;
      
      lockerCamera.transform.SetParent(null);
   }

   void switchToLockerCam()
   {
      playerCamera.enabled = false;
      lockerCamera.enabled = true;
   }
   
   private void OnTriggerEnter(Collider collision)  
   {
      if (collision.CompareTag("Player"))
      {
         canHideLocker = true;
      }
   }
   
   private void OnTriggerExit(Collider collision)
   {
      if (collision.CompareTag("Player"))
      {
         canHideLocker = false;
      }
   }

   void Update()
   {
      if (Input.GetKeyDown(KeyCode.E) && canHideLocker)
      {
         isHidingLocker = !isHidingLocker;
      }

      if (isHidingLocker)
      {
         lockerCamera.transform.SetParent(null);
         camera.parent = cameraLockerPos;
         player.SetActive(false);
         camera.position = cameraLockerPos.position;
         switchToLockerCam();
      }

      else
      {
         player.SetActive(true);
         lockerCamera.enabled = false;
         playerCamera.enabled = true;
      }
   }
   
}

问题原因

两个脚本同时操作同一个Player对象的激活状态,导致冲突:

  • 当玩家躲进桌子时,TriggerTable脚本会调用switchToTableCam()将Player设为隐藏,但TriggerLockerDoor脚本的Update方法中,因为isHidingLocker为false,每帧都会执行player.SetActive(true),直接覆盖了桌子脚本的设置,导致Player始终显示。

解决方法

方法1:统一管理隐藏状态

创建全局状态管理器,专门处理Player的隐藏/显示逻辑,避免多个脚本直接修改Player的active状态:

using UnityEngine;

public class HideManager : MonoBehaviour
{
    public static HideManager Instance;
    [SerializeField] private GameObject player;
    private bool isPlayerHidden;

    void Awake()
    {
        Instance = this;
        player = GameObject.Find("Player");
    }

    public void SetPlayerHidden(bool hidden)
    {
        if (isPlayerHidden != hidden)
        {
            isPlayerHidden = hidden;
            player.SetActive(!hidden);
        }
    }
}

修改两个脚本中的Player激活逻辑:

  • 在TriggerTable的switchToTableCam()中替换player.SetActive(false)为HideManager.Instance.SetPlayerHidden(true)
  • 在switchToPlayerCam()中替换player.SetActive(true)为HideManager.Instance.SetPlayerHidden(false)
  • 在TriggerLockerDoor的隐藏分支中替换player.SetActive(false)为HideManager.Instance.SetPlayerHidden(true)
  • 在else分支中替换player.SetActive(true)为HideManager.Instance.SetPlayerHidden(false)

方法2:修改脚本逻辑,避免每帧重复设置

只在状态改变时修改Player的active状态,而非每帧执行:
以TriggerLockerDoor为例,添加状态标记,仅当状态变化时才更新Player:

// 在TriggerLockerDoor中添加变量
private bool wasHidingLocker;

void Update()
{
    if (Input.GetKeyDown(KeyCode.E) && canHideLocker)
    {
        isHidingLocker = !isHidingLocker;
    }

    if (isHidingLocker != wasHidingLocker)
    {
        wasHidingLocker = isHidingLocker;
        if (isHidingLocker)
        {
            lockerCamera.transform.SetParent(null);
            camera.parent = cameraLockerPos;
            player.SetActive(false);
            camera.position = cameraLockerPos.position;
            switchToLockerCam();
        }
        else
        {
            player.SetActive(true);
            lockerCamera.enabled = false;
            playerCamera.enabled = true;
        }
    }
}

对TriggerTable脚本做同样修改,添加wasHidingTable变量,仅在状态变化时执行Player的显示/隐藏逻辑,避免每帧重复设置导致的冲突。

内容的提问来源于stack exchange,提问作者heymasin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 09:42:02