Friday, September 21, 2018

unity - I'm still not sure how to control each door individual?


What I want to do is something more or less very simple. The main bool flag lockDoors control all the doors and this is working fine now. But now I want to add a flag to each individual door so I can change the door lock state for each specific door. And if I change the lockDoors state it will change all the doors except if I changed some individuals.


I tried to add a new class name DoorControl and made it also Serializable but not sure if this is the way and how to do it.


Example of how it should look like in the Inspector:


lockDoors checkbox here (This is the flag for all the doors) and then:


Door1
checkbox here
Door2
checkbox here
Door3
checkbox here

So I can keep controlling the whole doors or each door individual.


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

using System.Linq;
using UnityEngine;

public class DoorsLockManager : MonoBehaviour
{
[System.Serializable]
public class DoorControl
{
public bool doorLock;
}


public bool lockDoors = false;
public List _doors = new List();
public DoorControl[] doorscontrol;

private bool[] doorsLocks;
private Renderer rend;
private Shader unlitcolor;
private List DoorShieldFXLocked = new List();



private void Start()
{
DoorShieldFXLocked = GameObject.FindGameObjectsWithTag("DoorShield").ToList();
unlitcolor = Shader.Find("Unlit/ShieldFX");

var doors = GameObject.FindGameObjectsWithTag("Door");
foreach (var door in doors)
{
_doors.Add(door.GetComponent());

}

doorscontrol = new DoorControl[_doors.Count];

ChangeDoorsLockStates();
}

private void Update()
{
ChangeDoorsLockStates();

}

private void ChangeDoorsLockStates()
{
for (int i = 0; i < DoorShieldFXLocked.Count; i++)
{
if (lockDoors == true)
{
ChangeColors(Color.red, Color.green, i);
}

else
{
ChangeColors(Color.red, Color.green, i);
}
}

for (int x = 0; x < _doors.Count; x++)
{
if (lockDoors == true)
{

LockDoor(x);
}
else
{
UnlockDoor(x);
}
}
}

private void ChangeColors(Color32 lockedColor, Color32 unlockedColor, int index)

{
var renderer = DoorShieldFXLocked[index].GetComponent();
renderer.material.shader = Shader.Find("Unlit/ShieldFX");

if (lockDoors == true)
{
renderer.material.SetColor("_MainColor", lockedColor);
}
else
{

renderer.material.SetColor("_MainColor", unlockedColor);
}
}

public void LockDoor(int doorIndex)
{
_doors[doorIndex].ChangeLockState(true);
}
public void UnlockDoor(int doorIndex)
{

_doors[doorIndex].ChangeLockState(false);
}
}

And this script is attached to each door:


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

public class HoriDoorManager : MonoBehaviour

{
private List doors = new List();
private bool doorLockState;

private void Start()
{
if (transform.parent != null)
{
Transform parent = transform.parent;
var children = parent.GetComponentsInChildren();


if(children != null)
{
foreach (Transform door in children)
{
if (door.name == "Door_Left" || door.name == "Door_Right")
doors.Add(door.GetComponent());
}
}
}

}

void OnTriggerEnter()
{
if (doorLockState == false)
{
if (doors != null)
{
for(int i =0; i < doors.Count; i++)
{

doors[i].OpenDoor();
}
}
}
}

public void ChangeLockState(bool lockState)
{
doorLockState = lockState;
}

}

Answer



Okay I just did a mockup of what I think it is you want:


//each door has a DoorControl object which holds the bool variables and handles 
//changing the variables
[System.Serializable]
public class DoorControl
{
public bool doorLock;
public bool doorLockOverride;


public DoorControl(bool doorLock = true, bool doorLockOverride = false)
{
this.doorLock = doorLock;
this.doorLockOverride = doorLockOverride;
}

public void SetDoorLockState(bool val)
{
doorLock = val;

}
}


public class Door : MonoBehaviour
{
public DoorControl thisDoorControl;

private void Start()
{

thisDoorControl = new DoorControl();
}

private void Update()
{
if (thisDoorControl.doorLockOverride)
{
OpenDoor();
return;
}

if (thisDoorControl.doorLock)
{
OpenDoor();
}
else
{
CloseDoor();
}
}


private void OpenDoor()
{
//open your door
}

private void CloseDoor()
{
//close your door
}
}


You could then reference each doors DoorControl in your manager class and stuff it into a List or an DoorControl[] array like this:


public class DoorManager : MonoBehaviour
{
public List doors = new List();
public List doorControls = new List();

//this is just to initialize the list with values from all the doors. You could
//assign those directly in the inspector
private void Start()

{
foreach(var door in doors)
{
doorControls.Add(door.thisDoorControl);
}
}

public void ChangeAllLockOverrides(bool val)
{
foreach(var door in doorControls)

{
door.doorLockOverride = val;
}
}
}

The manager then looks like this in the inspector: Unity screenshot


Keep in mind that this will open/close the door every frame because I call it in Update. This is no good solution and you should not copy paste this if you plan to keep your performance as high as possible. I hope this points you in the right direction.


No comments:

Post a Comment

Simple past, Present perfect Past perfect

Can you tell me which form of the following sentences is the correct one please? Imagine two friends discussing the gym... I was in a good s...