385 lines
19 KiB
C#
385 lines
19 KiB
C#
|
using UnityEngine;
|
|||
|
using SoulGames.Utilities;
|
|||
|
|
|||
|
namespace SoulGames.EasyGridBuilderPro
|
|||
|
{
|
|||
|
public class GridObjectGhost : MonoBehaviour //This class handles displaying selected 'PlacedObjectType'
|
|||
|
{
|
|||
|
[Tooltip("Spawned Ghost object's layer. \nIMPORTANT: Set this to 'Ignore Raycast' layer.")]
|
|||
|
[SerializeField]private LayerMask ghostObjectLayer; //Layer that should be used
|
|||
|
|
|||
|
private Transform visual = null; //Visual reference
|
|||
|
private Transform parentObject;
|
|||
|
private EasyGridBuilderPro currentActiveSystem;
|
|||
|
private Material selectedMat = null;
|
|||
|
private bool updateFix = false;
|
|||
|
|
|||
|
private BoxCollider tempCollider;
|
|||
|
private Rigidbody tempRB;
|
|||
|
private ColliderBridgeGridObject colliderBridge;
|
|||
|
private Vector3 tempColliderScale;
|
|||
|
private Vector3 tempColliderCenter;
|
|||
|
|
|||
|
public static event OnBuildableObjectAreaBlockerEnterDelegate OnBuildableObjectAreaBlockerEnter;
|
|||
|
public delegate void OnBuildableObjectAreaBlockerEnterDelegate();
|
|||
|
public static event OnBuildableObjectAreaBlockerExitDelegate OnBuildableObjectAreaBlockerExit;
|
|||
|
public delegate void OnBuildableObjectAreaBlockerExitDelegate();
|
|||
|
|
|||
|
private void Start()
|
|||
|
{
|
|||
|
if (MultiGridManager.Instance.activeGridSystem == null) return;
|
|||
|
currentActiveSystem = MultiGridManager.Instance.activeGridSystem;
|
|||
|
|
|||
|
CleanObject();
|
|||
|
RefreshVisual();
|
|||
|
|
|||
|
MultiGridManager.Instance.OnActiveGridChanged += OnGridSystemChanged;
|
|||
|
foreach (EasyGridBuilderPro grid in MultiGridManager.Instance.easyGridBuilderProList)
|
|||
|
{
|
|||
|
grid.OnSelectedBuildableChanged += OnSelectedChanged;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void OnDestroy()
|
|||
|
{
|
|||
|
MultiGridManager.Instance.OnActiveGridChanged -= OnGridSystemChanged;
|
|||
|
foreach (EasyGridBuilderPro grid in MultiGridManager.Instance.easyGridBuilderProList)
|
|||
|
{
|
|||
|
grid.OnSelectedBuildableChanged -= OnSelectedChanged;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void OnSelectedChanged(object sender, System.EventArgs e)
|
|||
|
{
|
|||
|
//Debug.Log("OnSelectedChanged");
|
|||
|
CleanObject();
|
|||
|
RefreshVisual();
|
|||
|
}
|
|||
|
|
|||
|
private void OnGridSystemChanged(EasyGridBuilderPro currentActiveSystem)
|
|||
|
{
|
|||
|
//Debug.Log("OnGirdSystemChanged");
|
|||
|
this.currentActiveSystem = currentActiveSystem;
|
|||
|
BuildableGridObjectTypeSO buildableGridObjectTypeSO = currentActiveSystem.GetBuildableGridObjectTypeSO();
|
|||
|
CleanObject();
|
|||
|
RefreshVisual();
|
|||
|
}
|
|||
|
|
|||
|
private void Update()
|
|||
|
{
|
|||
|
if (MultiGridManager.Instance.activeGridSystem == null) return;
|
|||
|
|
|||
|
currentActiveSystem = MultiGridManager.Instance.activeGridSystem;
|
|||
|
BuildableGridObjectTypeSO buildableGridObjectTypeSO = currentActiveSystem.GetBuildableGridObjectTypeSO(); //Call 'GetBuildableGridObjectTypeSO' function in 'GridBuildingSystem3D' and assign returned value to 'buildableGridObjectTypeSO'
|
|||
|
|
|||
|
if (visual != null)
|
|||
|
{
|
|||
|
if (currentActiveSystem.GetGridMode() != GridMode.Build)
|
|||
|
{
|
|||
|
Destroy(parentObject.gameObject);
|
|||
|
parentObject = null;
|
|||
|
visual = null;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (!MultiGridManager.Instance.onGrid)
|
|||
|
{
|
|||
|
if (visual != null)
|
|||
|
{
|
|||
|
Destroy(parentObject.gameObject);
|
|||
|
parentObject = null;
|
|||
|
visual = null;
|
|||
|
updateFix = true;
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
if (updateFix)
|
|||
|
{
|
|||
|
CleanObject();
|
|||
|
RefreshVisual();
|
|||
|
updateFix = false;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void LateUpdate()
|
|||
|
{
|
|||
|
if (MultiGridManager.Instance.activeGridSystem == null) return;
|
|||
|
|
|||
|
if (currentActiveSystem.gridAxis == GridAxis.XZ)
|
|||
|
{
|
|||
|
Vector3 targetPosition = currentActiveSystem.GetMouseWorldSnappedPosition(); //Call 'GetMouseWorldSnappedPosition' in 'GridBuildingSystem3D' and assign the returned position in 'targetPosition'
|
|||
|
transform.position = Vector3.Lerp(transform.position, new Vector3(targetPosition.x, currentActiveSystem.GetGridOrigin().y, targetPosition.z), Time.deltaTime * 25f); //Smoothly lerp through the current position and 'targetPosition'
|
|||
|
transform.rotation = Quaternion.Lerp(transform.rotation, currentActiveSystem.GetPlacedObjectRotation(), Time.deltaTime * 25f); //Smoothly lerp through the current rotation and target rotation grabbed from 'GetPlacedObjectRotation' fuction
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
Vector3 targetPosition = currentActiveSystem.GetMouseWorldSnappedPosition(); //Call 'GetMouseWorldSnappedPosition' in 'GridBuildingSystem3D' and assign the returned position in 'targetPosition'
|
|||
|
transform.position = Vector3.Lerp(transform.position, new Vector3(targetPosition.x, targetPosition.y, currentActiveSystem.GetGridOrigin().z), Time.deltaTime * 25f); //Smoothly lerp through the current position and 'targetPosition'
|
|||
|
transform.rotation = Quaternion.Lerp(transform.rotation, currentActiveSystem.GetPlacedObjectRotation(), Time.deltaTime * 25f); //Smoothly lerp through the current rotation and target rotation grabbed from 'GetPlacedObjectRotation' fuction
|
|||
|
}
|
|||
|
|
|||
|
BuildableGridObjectTypeSO buildableGridObjectTypeSO = currentActiveSystem.GetBuildableGridObjectTypeSO(); //Call 'GetBuildableGridObjectTypeSO' function in 'GridBuildingSystem3D' and assign returned value to 'buildableGridObjectTypeSO'
|
|||
|
if (visual != null) HandleVisualColor(buildableGridObjectTypeSO);
|
|||
|
}
|
|||
|
|
|||
|
private void RefreshVisual() //This function is used to refresh the visual object
|
|||
|
{
|
|||
|
if (visual != null) //If 'visual' is not empty
|
|||
|
{
|
|||
|
Destroy(parentObject.gameObject); //Destroy 'visual' game object
|
|||
|
parentObject = null;
|
|||
|
visual = null; //And assign 'visual' to null
|
|||
|
}
|
|||
|
|
|||
|
BuildableGridObjectTypeSO buildableGridObjectTypeSO = currentActiveSystem.GetBuildableGridObjectTypeSO(); //Call 'GetBuildableGridObjectTypeSO' function in 'GridBuildingSystem3D' and assign returned value to 'buildableGridObjectTypeSO'
|
|||
|
|
|||
|
if (buildableGridObjectTypeSO != null) //If 'buildableGridObjectTypeSO' is not empty(If currently a 'buildableGridObjectType' is selected)
|
|||
|
{
|
|||
|
if (buildableGridObjectTypeSO.ghostPrefab == null)
|
|||
|
{
|
|||
|
buildableGridObjectTypeSO.ghostPrefab = buildableGridObjectTypeSO.objectPrefab[0]; //If 'buildableGridObjectTypeSO' visual is empty then use the 'prefab' as the 'visual'
|
|||
|
}
|
|||
|
|
|||
|
visual = Instantiate(buildableGridObjectTypeSO.ghostPrefab, Vector3.zero, Quaternion.identity); //Instantiate the visual game object and cache it in 'visual'
|
|||
|
|
|||
|
HandleVisualColor(buildableGridObjectTypeSO);
|
|||
|
|
|||
|
visual.parent = transform; //Attach 'visual' game object under this game objects transform as a child
|
|||
|
visual.localPosition = Vector3.zero; //Change position of 'visual' to 0, 0, 0
|
|||
|
visual.localEulerAngles = Vector3.zero; //Change rotation of 'visual' to 0, 0, 0
|
|||
|
|
|||
|
parentObject = new GameObject(buildableGridObjectTypeSO.name).transform;
|
|||
|
parentObject.parent = transform;
|
|||
|
parentObject.localPosition = Vector3.zero;
|
|||
|
parentObject.localEulerAngles = Vector3.zero;
|
|||
|
parentObject.localScale = new Vector3(parentObject.localScale.x + 0.01f, parentObject.localScale.y + 0.01f, parentObject.localScale.z + 0.01f);
|
|||
|
BuildableGridObject buildableGridObject = visual.GetComponent<BuildableGridObject>();
|
|||
|
|
|||
|
if (currentActiveSystem.gridAxis == GridAxis.XY)
|
|||
|
{
|
|||
|
if (buildableGridObject.IsRotateObjectForXY())
|
|||
|
{
|
|||
|
visual.localEulerAngles = new Vector3(-90, 0, 0);
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
if (buildableGridObject.IsRotateObjectForXZ())
|
|||
|
{
|
|||
|
visual.localEulerAngles = new Vector3(90, 0, 0);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
visual.parent = parentObject;
|
|||
|
Vector2Int offset = buildableGridObjectTypeSO.CalculatePlacedObjectSize(currentActiveSystem.GetGridCellSize());
|
|||
|
if (currentActiveSystem.gridAxis == GridAxis.XZ)
|
|||
|
{
|
|||
|
parentObject.localPosition = new Vector3(offset.x * currentActiveSystem.GetGridCellSize() / 2, visual.localPosition.y, offset.y * currentActiveSystem.GetGridCellSize() / 2);
|
|||
|
if (buildableGridObject.IsRotateObjectForXZ())
|
|||
|
{
|
|||
|
parentObject.localPosition = new Vector3(parentObject.localPosition.x - buildableGridObject.GetObjectPivotOffset().x, parentObject.localPosition.y - buildableGridObject.GetObjectPivotOffset().z, parentObject.localPosition.z - buildableGridObject.GetObjectPivotOffset().y);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
parentObject.localPosition = new Vector3(parentObject.localPosition.x - buildableGridObject.GetObjectPivotOffset().x, parentObject.localPosition.y - buildableGridObject.GetObjectPivotOffset().y, parentObject.localPosition.z - buildableGridObject.GetObjectPivotOffset().z);
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
parentObject.localPosition = new Vector3(offset.x * currentActiveSystem.GetGridCellSize() / 2, offset.y * currentActiveSystem.GetGridCellSize() / 2, visual.localPosition.z);
|
|||
|
if (buildableGridObject.IsRotateObjectForXY())
|
|||
|
{
|
|||
|
parentObject.localPosition = new Vector3(parentObject.localPosition.x - buildableGridObject.GetObjectPivotOffset().x, parentObject.localPosition.y - buildableGridObject.GetObjectPivotOffset().z, parentObject.localPosition.z + buildableGridObject.GetObjectPivotOffset().y);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
parentObject.localPosition = new Vector3(parentObject.localPosition.x - buildableGridObject.GetObjectPivotOffset().x, parentObject.localPosition.y - buildableGridObject.GetObjectPivotOffset().y, parentObject.localPosition.z + buildableGridObject.GetObjectPivotOffset().z);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
tempColliderScale = buildableGridObject.GetRawObjectScale();
|
|||
|
tempColliderCenter = buildableGridObject.GetRawObjectCenter();
|
|||
|
tempCollider = parentObject.gameObject.AddComponent<BoxCollider>();
|
|||
|
|
|||
|
if (currentActiveSystem.gridAxis == GridAxis.XZ)
|
|||
|
{
|
|||
|
if (buildableGridObject.IsRotateObjectForXZ())
|
|||
|
{
|
|||
|
tempCollider.isTrigger = true;
|
|||
|
tempCollider.size = new Vector3(tempColliderScale.x, tempColliderScale.z, tempColliderScale.y);
|
|||
|
tempCollider.center = new Vector3(tempColliderCenter.x, -tempColliderCenter.z, tempColliderCenter.y);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
tempCollider.isTrigger = true;
|
|||
|
tempCollider.size = tempColliderScale;
|
|||
|
tempCollider.center = tempColliderCenter;
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
if (buildableGridObject.IsRotateObjectForXY())
|
|||
|
{
|
|||
|
tempCollider.isTrigger = true;
|
|||
|
tempCollider.size = new Vector3(tempColliderScale.x, tempColliderScale.z, tempColliderScale.y);
|
|||
|
tempCollider.center = new Vector3(tempColliderCenter.x, tempColliderCenter.z, -tempColliderCenter.y);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
tempCollider.isTrigger = true;
|
|||
|
tempCollider.size = tempColliderScale;
|
|||
|
tempCollider.center = tempColliderCenter;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
colliderBridge = parentObject.gameObject.AddComponent<ColliderBridgeGridObject>();
|
|||
|
|
|||
|
tempRB = parentObject.gameObject.AddComponent<Rigidbody>();
|
|||
|
tempRB.isKinematic = true;
|
|||
|
|
|||
|
SetLayerRecursive(parentObject.gameObject, LayerNumber()); //Call function 'SetLayerRecursive'
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void CleanObject()
|
|||
|
{
|
|||
|
if (tempCollider)
|
|||
|
{
|
|||
|
OnBuildableObjectAreaBlockerExit?.Invoke();
|
|||
|
DestroyImmediate(tempCollider);
|
|||
|
DestroyImmediate(colliderBridge);
|
|||
|
DestroyImmediate(tempRB);
|
|||
|
tempCollider = null;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public void OnTriggerEnter(Collider other)
|
|||
|
{
|
|||
|
if (other.gameObject.GetComponent<BuildableObjectAreaBlocker>())
|
|||
|
{
|
|||
|
OnBuildableObjectAreaBlockerEnter?.Invoke();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public void OnTriggerExit(Collider other)
|
|||
|
{
|
|||
|
if (other.gameObject.GetComponent<BuildableObjectAreaBlocker>())
|
|||
|
{
|
|||
|
OnBuildableObjectAreaBlockerExit?.Invoke();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public void OnTriggerStay(Collider other)
|
|||
|
{
|
|||
|
if (other.gameObject.GetComponent<BuildableObjectAreaBlocker>())
|
|||
|
{
|
|||
|
OnBuildableObjectAreaBlockerEnter?.Invoke();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void HandleVisualColor(BuildableGridObjectTypeSO buildableGridObjectTypeSO)
|
|||
|
{
|
|||
|
if (currentActiveSystem.NotPlaceableVisualCallerBuildableGridObject() == false)
|
|||
|
{
|
|||
|
if (buildableGridObjectTypeSO.notPlaceableGhostMaterial != null) //If in 'buildableGridObjectTypeSO' a 'customeVisualMaterial' is provided
|
|||
|
{
|
|||
|
selectedMat = buildableGridObjectTypeSO.notPlaceableGhostMaterial;
|
|||
|
}
|
|||
|
else if (buildableGridObjectTypeSO.placeableGhostMaterial != null) //If in 'buildableGridObjectTypeSO' a 'customeVisualMaterial' is provided
|
|||
|
{
|
|||
|
selectedMat = buildableGridObjectTypeSO.placeableGhostMaterial;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
selectedMat = null;
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
if (buildableGridObjectTypeSO.placeableGhostMaterial != null) //If in 'buildableGridObjectTypeSO' a 'customeVisualMaterial' is provided
|
|||
|
{
|
|||
|
selectedMat = buildableGridObjectTypeSO.placeableGhostMaterial;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
selectedMat = null;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (selectedMat != null)
|
|||
|
{
|
|||
|
GameObject newVisual1 = null;
|
|||
|
GameObject newVisual2 = null;
|
|||
|
GameObject newVisual3 = null;
|
|||
|
GameObject newVisual4 = null;
|
|||
|
|
|||
|
if (visual.GetComponent<MeshRenderer>()) //If the child object has a material
|
|||
|
{
|
|||
|
visual.GetComponent<MeshRenderer>().material = selectedMat; //Replace current material in the child object with provided 'customeVisualMaterial'
|
|||
|
}
|
|||
|
|
|||
|
for (int firstChild = 0; firstChild < visual.childCount; firstChild++) //Loop through all the child objects in 'visual'
|
|||
|
{
|
|||
|
newVisual1 = visual.GetChild(firstChild).gameObject;
|
|||
|
if (newVisual1.GetComponent<MeshRenderer>()) //If the child object has a material
|
|||
|
{
|
|||
|
newVisual1.GetComponent<MeshRenderer>().material = selectedMat; //Replace current material in the child object with provided 'customeVisualMaterial'
|
|||
|
}
|
|||
|
|
|||
|
for (int secondChild = 0; secondChild < newVisual1.transform.childCount; secondChild++) //Loop through all the child objects in 'newVisual'
|
|||
|
{
|
|||
|
newVisual2 = newVisual1.transform.GetChild(secondChild).gameObject;
|
|||
|
if (newVisual2.GetComponent<MeshRenderer>()) //If the child object has a material
|
|||
|
{
|
|||
|
newVisual2.GetComponent<MeshRenderer>().material = selectedMat; //Replace current material in the child object with provided 'customeVisualMaterial'
|
|||
|
}
|
|||
|
|
|||
|
for (int thridChild = 0; thridChild < newVisual2.transform.childCount; thridChild++) //Loop through all the child objects in 'newVisual'
|
|||
|
{
|
|||
|
newVisual3 = newVisual2.transform.GetChild(thridChild).gameObject;
|
|||
|
if (newVisual3.GetComponent<MeshRenderer>()) //If the child object has a material
|
|||
|
{
|
|||
|
newVisual3.GetComponent<MeshRenderer>().material = selectedMat; //Replace current material in the child object with provided 'customeVisualMaterial'
|
|||
|
}
|
|||
|
|
|||
|
for (int fourthChild = 0; fourthChild < newVisual3.transform.childCount; fourthChild++) //Loop through all the child objects in 'newVisual'
|
|||
|
{
|
|||
|
newVisual4 = newVisual3.transform.GetChild(fourthChild).gameObject;
|
|||
|
if (newVisual4.GetComponent<MeshRenderer>()) //If the child object has a material
|
|||
|
{
|
|||
|
newVisual4.GetComponent<MeshRenderer>().material = selectedMat; //Replace current material in the child object with provided 'customeVisualMaterial'
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private int LayerNumber() //This function grab 'ghostObjectLayer' and return layer int vlaue
|
|||
|
{
|
|||
|
int layerNumber = 0;
|
|||
|
int layer = ghostObjectLayer.value;
|
|||
|
while(layer > 0)
|
|||
|
{
|
|||
|
layer = layer >> 1;
|
|||
|
layerNumber++;
|
|||
|
}
|
|||
|
if (layerNumber > 1) return layerNumber - 1;
|
|||
|
else return 0;
|
|||
|
}
|
|||
|
|
|||
|
private void SetLayerRecursive(GameObject targetGameObject, int layer) //Change 'visual' object's and it's children's layer
|
|||
|
{
|
|||
|
targetGameObject.layer = layer; //Set passed object's layer
|
|||
|
foreach (Transform child in targetGameObject.transform) //Loop through all the child objects
|
|||
|
{
|
|||
|
SetLayerRecursive(child.gameObject, layer); //Call the function again but pass the child object
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|