Странно, почему при смене цвета дверей он меняется для всех дверей, а не для каждой двери индивидуально? - PullRequest
0 голосов
/ 01 мая 2020

Этот сценарий прикреплен к пустому GameObject с помощью ExecuteAlways, поэтому он будет работать и в режиме редактирования, и в режиме выполнения:

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

[ExecuteAlways]
public class DoorsLockManager : MonoBehaviour
{
    public List<HoriDoorManager> Doors = new List<HoriDoorManager>();
    public List<bool> DoorsLockState = new List<bool>();

    // Start is called before the first frame update
    void Start()
    {

    }

    // Update is called once per frame
    void Update()
    {
        if (Doors.Count == 0 || DoorsLockState.Count == 0)
        {
            Doors = FindObjectsOfType<HoriDoorManager>().ToList();
            DoorsLockState = new bool[Doors.Count].ToList();
        }

        for (int i = 0; i < DoorsLockState.Count; i++)
        {
            Doors[i].lockState = DoorsLockState[i];
        }
    }
}

И этот сценарий прикреплен к каждой двери также в этом сценарии. используя атрибут ExecuteAlways:

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

[ExecuteAlways]
public class HoriDoorManager : MonoBehaviour
{
    public DoorHori door1;
    public DoorHori door2;
    public bool lockState;

    private List<Material> doorsRenderers = new List<Material>();

    private void Start()
    {
        doorsRenderers.Add(door1.transform.GetChild(0).GetComponent<Renderer>().sharedMaterial);
        doorsRenderers.Add(door2.transform.GetChild(0).GetComponent<Renderer>().sharedMaterial);
        doorsRenderers[0].shader = Shader.Find("Unlit/ShieldFX");
        doorsRenderers[1].shader = Shader.Find("Unlit/ShieldFX");
    }

    void OnTriggerEnter()
    {
        if (lockState == false)
        {
            if (door1 != null)
            {
                door1.OpenDoor();
            }

            if (door2 != null)
            {
                door2.OpenDoor();
            }
        }
    }

    private void Update()
    {
        if(lockState == false)
        {
            doorsRenderers[0].SetColor("_MainColor", Color.green);
        }
        else
        {
            doorsRenderers[0].SetColor("_MainColor", Color.red);
        }
    }
}

Проблема в том, что когда я меняю состояние флага в первом скрипте в списке DoorsLockState, он не меняет цвета дверей, только один флаг меняет цвет для все двери.

Это меняет состояние блокировки, но я хочу, чтобы каждая дверь также меняла цвет в соответствии с состоянием блокировки. Замок = Красный Разблокировка = Зеленый.

Класс DoorHori:

using UnityEngine;
using System.Collections;

public class DoorHori : MonoBehaviour {

    public float translateValue;
    public float easeTime;
    public OTween.EaseType ease;
    public float waitTime;

    private Vector3 StartlocalPos;
    private Vector3 endlocalPos;

    private void Start(){
        StartlocalPos = transform.localPosition;    
        gameObject.isStatic = false;
    }

    public void OpenDoor(){
        OTween.ValueTo( gameObject,ease,0.0f,-translateValue,easeTime,0.0f,"StartOpen","UpdateOpenDoor","EndOpen");
        GetComponent<AudioSource>().Play();
    }

    private void UpdateOpenDoor(float f){       
        Vector3 pos = transform.TransformDirection( new Vector3( 1,0,0));
        transform.localPosition = StartlocalPos + pos*f;

    }

    private void UpdateCloseDoor(float f){      
        Vector3 pos = transform.TransformDirection( new Vector3( -f,0,0)) ;

        transform.localPosition = endlocalPos-pos;

    }

    private void EndOpen(){
        endlocalPos = transform.localPosition ;
        StartCoroutine( WaitToClose());
    }

    private IEnumerator WaitToClose(){

        yield return new WaitForSeconds(waitTime);
        OTween.ValueTo( gameObject,ease,0.0f,translateValue,easeTime,0.0f,"StartClose","UpdateCloseDoor","EndClose");
        GetComponent<AudioSource>().Play();
    }
}

Ответы [ 2 ]

0 голосов
/ 01 мая 2020

Если вы используете один и тот же материал и измените цвет в шейдере, он изменит все, лучше иметь два материала и применять их соответствующим образом.

Для блокировки разблокируйте два материала, один для блокировки. Есть ссылка на эти цвета в скрипте ie (установлен в инспекторе)

public Material greenMat, redMat;

Когда вы хотите, чтобы он был разблокирован

door.GetComponent<MeshRenderer>().material = greenMat;

Заблокировано

door.GetComponent<MeshRenderer>().material = redMat;
0 голосов
/ 01 мая 2020

Вы редактируете sharedMaterial, который используется всеми вашими дверями

doorsRenderers.Add(door1.transform.GetChild(0).GetComponent<Renderer>().sharedMaterial);
//Notice the ".shadredMaterial" at the end here

Вместо экземпляра материала.

с помощью doorsRenderers[0].shader = Shader.Find("Unlit/ShieldFX"); вы также получаете прямой доступ к шейдеру, что означает, что любые изменения, внесенные в него, будут отражаться на каждом экземпляре этого материала.

doorsRenderers[0].SetColor("_MainColor", Color.green); также напрямую обращается к материалу и нижележащему шейдеру, а не к экземпляру материала (по умолчанию Unity создает экземпляр материала при редактировании материала во время выполнения)

Там go можно исправить двумя способами:

  • Используйте два разных материала (один красный, один зеленый) и замените материал на нужный.
  • Получите GameObjects 'Renderer вместо (общего) материала и примените изменение цвета, используя вместо этого свойство Renderer.material.color. Это создаст экземпляр материала, изменив только цвет этого экземпляра.

Решение два будет выглядеть примерно так:

private List<Renderer> doorsRenderers = new List<Renderer>();

private void Start()
{
    doorsRenderers.Add(door1.transform.GetChild(0).GetComponent<Renderer>());
    doorsRenderers.Add(door2.transform.GetChild(0).GetComponent<Renderer>());
}

private void ChangeDoorColour()
{
    if(lockState == false)
    {
        doorsRenderers[0].material.color = Color.green;
    }
    else
    {
       doorsRenderers[0].material.color = Color.red;
    }
}

В качестве отступления: вы устанавливаете цвет материала вашего Сделайте это в обновлении l oop, это не очень хорошая вещь, и ее следует делать только тогда, когда состояние дверей меняется. Поэтому я поместил ее в отдельную функцию ChangeDoorColour(), которая должна вызываться только при изменении состояния двери (так, вероятно, в методах OpenDoor() и CloseDoor()).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...