using UnityEngine;
// Sci-Fi Ship Controller. Copyright (c) 2018-2023 SCSM Pty Ltd. All rights reserved.
namespace SciFiShipController
{
///
/// Demo script to cycle through two or more materials on an object.
/// WARNING
/// If you want to modify this script, create a new script in your own namespace
/// and copy over the code you need. DO NOT MODIFY this script as it will be
/// overwritten when you do the next SSC update.
/// This script has NOT been performance tested...
///
public class DemoSSCCycleMaterials : MonoBehaviour
{
#region Public Variables
public MeshRenderer objectMeshRenderer = null;
[Header("Group1 Material")]
[Range(0, 9)] public int group1MatElementIndex = 0;
[Range(0.01f, 10f)] public float group1SwitchInterval = 0.1f;
[Range(0f, 30f)] public float group1ActivateDelay = 0f;
[Range(0f, 30f)] public float group1DeactivateDelay = 0f;
public bool group1StartOn = false;
public Material[] group1Materials;
[Header("Group2 Material")]
[Range(0, 9)] public int group2MatElementIndex = 1;
[Range(0.01f, 10f)] public float group2SwitchInterval = 0.1f;
[Range(0f, 30f)] public float group2ActivateDelay = 0f;
[Range(0f, 30f)] public float group2DeactivateDelay = 0f;
public bool group2StartOn = false;
public Material[] group2Materials;
[Header("Group3 Material")]
[Range(0, 9)] public int group3MatElementIndex = 2;
[Range(0.01f, 10f)] public float group3SwitchInterval = 0.1f;
[Range(0f, 30f)] public float group3ActivateDelay = 0f;
[Range(0f, 30f)] public float group3DeactivateDelay = 0f;
public bool group3StartOn = false;
public Material[] group3Materials;
#endregion
#region Private Variables
private bool isInitialised = false;
private Material[] materialAray;
private int numMaterialsOnObject = 0;
private bool[] isGroupActive;
private bool[] isGroupValid;
private int[] currentGroupMatIndex;
private int[] numMaterialsArray;
private float[] groupTimer;
#endregion
#region Initialise Methods
// Start is called before the first frame update
void Start()
{
if (objectMeshRenderer == null)
{
#if UNITY_EDITOR
Debug.LogWarning("ERROR DemoSSCCycleMaterials - could not find mesh renderer for " + name);
#endif
}
else
{
materialAray = objectMeshRenderer.materials;
numMaterialsOnObject = materialAray == null ? 0 : materialAray.Length;
numMaterialsArray = new int[]
{ group1Materials == null ? 0 : group1Materials.Length,
group2Materials == null ? 0 : group2Materials.Length,
group3Materials == null ? 0 : group3Materials.Length };
if (numMaterialsOnObject < 1)
{
#if UNITY_EDITOR
Debug.LogWarning("ERROR DemoSSCCycleMaterials - could not find any materials on the mesh renderer (" + objectMeshRenderer.name + ") for " + name);
#endif
}
// Are there any materials to switch?
else if (numMaterialsArray != null && numMaterialsArray.Length == 3 && (numMaterialsArray[0] > 0 || numMaterialsArray[1] > 0 || numMaterialsArray[2] > 0))
{
isGroupValid = new bool[] { false, false, false };
ValidateGroup(1);
ValidateGroup(2);
ValidateGroup(3);
// At least one of the groups must be valid
if (isGroupValid[0] || isGroupValid[1] && isGroupValid[2])
{
groupTimer = new float[] { 0f, 0f, 0f };
currentGroupMatIndex = new int[] { 0, 0, 0 };
isGroupActive = new bool[] { group1StartOn, group2StartOn, group3StartOn };
isInitialised = true;
EnableGroup(1, group1StartOn);
EnableGroup(2, group2StartOn);
EnableGroup(3, group3StartOn);
}
}
}
}
private bool ValidateGroup(int groupNumber)
{
int groupMatElementIndex = groupNumber == 1 ? group1MatElementIndex : groupNumber == 2 ? group2MatElementIndex : group3MatElementIndex;
isGroupValid[groupNumber - 1] = numMaterialsArray[groupNumber - 1] > 0 && groupMatElementIndex >= 0 && groupMatElementIndex < numMaterialsOnObject;
if (!isGroupValid[groupNumber - 1] && numMaterialsArray[groupNumber - 1] > 0 && (groupMatElementIndex < 0 || groupMatElementIndex > numMaterialsOnObject - 1))
{
#if UNITY_EDITOR
Debug.LogWarning("ERROR DemoSSCCycleMaterials - group" + groupNumber + "MatElementIndex for " + name + " must be in the range 0 to " + (numMaterialsOnObject - 1).ToString());
#endif
}
return isGroupValid[groupNumber - 1];
}
#endregion
#region Update Methods
// Update is called once per frame
void Update()
{
if (isInitialised)
{
// Loop through all the groups
for (int groupNumber = 1; groupNumber < 4; groupNumber++)
{
// Is this group active?
if (isGroupActive[groupNumber - 1])
{
CheckSwitchingStatus(groupNumber);
}
}
}
}
#endregion
#region Private Methods
///
/// Check if we need to switch any materials
///
///
private void CheckSwitchingStatus(int groupNumber)
{
float groupFlashInterval = groupNumber == 1 ? group1SwitchInterval : groupNumber == 2 ? group2SwitchInterval : group3SwitchInterval;
if (groupFlashInterval > 0f && isGroupValid[groupNumber - 1])
{
// If past the interval time, get the next material
if (groupTimer[groupNumber - 1] > groupFlashInterval)
{
groupTimer[groupNumber - 1] = 0f;
// Get the next material in the list we are cycling through
++currentGroupMatIndex[groupNumber - 1];
// If past the end of the array of materials to change, go back to the start
if (currentGroupMatIndex[groupNumber - 1] > numMaterialsArray[groupNumber - 1] - 1) { currentGroupMatIndex[groupNumber - 1] = 0; }
Material mat = groupNumber == 1 ? group1Materials[currentGroupMatIndex[groupNumber - 1]] :
groupNumber == 2 ? group2Materials[currentGroupMatIndex[groupNumber - 1]] :
group3Materials[currentGroupMatIndex[groupNumber - 1]];
SwitchMaterial(groupNumber, mat);
}
else
{
// Increment the time for this group
groupTimer[groupNumber - 1] += Time.deltaTime;
}
}
}
///
/// Call this method with a delay
///
private void DisableGroup1()
{
EnableGroup(1, false);
}
///
/// Call this method with a delay
///
private void DisableGroup2()
{
EnableGroup(2, false);
}
///
/// Call this method with a delay
///
private void DisableGroup3()
{
EnableGroup(3, false);
}
///
/// Call this method with a delay
///
private void EnableGroup1()
{
EnableGroup(1, true);
}
///
/// Call this method with a delay
///
private void EnableGroup2()
{
EnableGroup(2, true);
}
// Call this method with a delay
private void EnableGroup3()
{
EnableGroup(3, true);
}
///
/// Enable or disable the group to switch materials
///
///
///
private void EnableGroup(int groupNumber, bool isEnabled)
{
if (isInitialised && groupNumber > 0 && groupNumber < 4 && isGroupValid[groupNumber - 1])
{
// Remember if the group is active or inactive
isGroupActive[groupNumber - 1] = isEnabled;
// Reset the group timer
groupTimer[groupNumber - 1] = 0f;
}
}
///
/// Attempt to switch or replace the material on the mesh renderer
/// for this instance of the object in the scene.
///
///
private void SwitchMaterial(int groupNumber, Material material)
{
if (isInitialised && groupNumber > 0 && groupNumber < 4 && material != null && objectMeshRenderer != null)
{
// Get the zero-based material element index we are going to replace on the renderer.
int materialElementIndex = groupNumber == 1 ? group1MatElementIndex : groupNumber == 2 ? group2MatElementIndex : group3MatElementIndex;
materialAray[materialElementIndex] = material;
objectMeshRenderer.materials = materialAray;
}
}
#endregion
#region Public Methods
///
/// Start the group switching materials. Valid numbers are between 1 and 3.
///
///
public void TurnGroupOn(int groupNumber)
{
if (groupNumber == 1 && group1ActivateDelay > 0f)
{
Invoke("EnableGroup1", group1ActivateDelay);
}
else if (groupNumber == 2 && group2ActivateDelay > 0f)
{
Invoke("EnableGroup2", group2ActivateDelay);
}
else if (groupNumber == 3 && group3ActivateDelay > 0f)
{
Invoke("EnableGroup3", group3ActivateDelay);
}
else
{
EnableGroup(groupNumber, true);
}
}
///
/// Stop the group switching materials. Valid numbers are between 1 and 3.
///
///
public void TurnGroupOff(int groupNumber)
{
if (groupNumber == 1 && group1DeactivateDelay > 0f)
{
Invoke("DisableGroup1", group1DeactivateDelay);
}
else if (groupNumber == 2 && group2DeactivateDelay > 0f)
{
Invoke("DisableGroup2", group2DeactivateDelay);
}
else if (groupNumber == 3 && group3DeactivateDelay > 0f)
{
Invoke("DisableGroup3", group3DeactivateDelay);
}
else
{
EnableGroup(groupNumber, false);
}
}
#endregion
}
}