BITFALL/Assets/Plugins/FImpossible Creations/Plugins - Level Design/Pipe Generator/PipeGenerator.cs

168 lines
7.5 KiB
C#
Raw Normal View History

2023-11-30 00:23:23 +08:00
using UnityEngine;
namespace FIMSpace.Generating
{
[AddComponentMenu("FImpossible Creations/Level Design/Pipe Generator", 3)]
public partial class PipeGenerator : MonoBehaviour, IGenerating
{
[SerializeField] [HideInInspector] private PipePreset projectPreset;
[SerializeField] private PipePreset.PipePresetData componentPreset;
public void SetPreset(PipePreset p) { projectPreset = p; }
public PipePreset.PipePresetData PresetData { get { return projectPreset ? projectPreset.Data : componentPreset; } }
[Tooltip("If pipe should be generated when game starts (if no pipe is generated in Editor mode)")]
public bool GenerateOnStart = true;
[FPD_Header("Segments path generate conditions")]
public Transform DesiredEnding;
public Vector3? CustomEndingPosition = null;
//public Vector3 EndPosition { get { return CustomEndingPosition == null ? DesiredEnding.position : CustomEndingPosition.Value; } }
public Vector3 EndPosition { get { if (DesiredEnding == null) { return CustomEndingPosition == null ? transform.position : CustomEndingPosition.Value; } else return CustomEndingPosition == null ? DesiredEnding.position : CustomEndingPosition.Value; } }
public Vector3? CustomEndingDirection = null;
//public Vector3 EndDirection { get { return CustomEndingDirection == null ? DesiredEnding.forward : CustomEndingDirection.Value; } }
public Vector3 EndDirection { get { if (DesiredEnding == null) { return CustomEndingDirection == null ? transform.forward : CustomEndingDirection.Value; } else return CustomEndingDirection == null ? DesiredEnding.forward : CustomEndingDirection.Value; } }
[Tooltip("Pipe can't finish in exact position of 'Desired Ending' point, but you can determinate how far from this point pipe ending process can start")]
public float MaxDistanceToEnding = 4f;
[Tooltip("How many times algorithm can iterate to find right path towards desired position")]
public int MaxTries = 128;
[Space(2)]
[Tooltip("If you want to use raycasting and run finish-align process with additional segments")]
public bool AlignFinish = true;
[Tooltip("Collision mask for finding end align point")]
public LayerMask AlignFinishOptionalsOn;
[Space(4)]
[Tooltip("Not allowing to generate pipe segments when couldn't find path towards target position, if untoggled pipe will be generate lastest unfinished segments-path")]
public bool DontGenerateIfNotEnded = true;
[Tooltip("If first iteration segments should have disabled collision checking, useful when you start pipe from inside of some collider")]
public int FirstSegmentsWithoutCollision = 1;
[Tooltip("Squasing / scaling down last segments to not go through walls when segment model is too long in it's size")]
public bool AlignScaleForFinishingSegments = true;
[FPD_Header("Align Start Properties")]
[Tooltip("Raycast collision mask for start alignment search")]
public LayerMask AlignStartOn;
[Tooltip("How far finish collision point can be away from game object's position")]
public float AlignStartMaxDistance = 2.5f;
[Tooltip("You can choose in which directions start align point should be search")]
public Vector3[] AlignStartDirections = new Vector3[] { Vector3.right, -Vector3.right, Vector3.up, Vector3.back };
[FPD_Header("Raycasting Collision")]
[Tooltip("Collision mask for detecting obstacles in segments-path way")]
public LayerMask ObstaclesMask;
[Tooltip("Box cast scale for detecting obstacles, you can preview it's size with scene gizmos")]
public float BoxcastScale = 0f;
[Tooltip("Using bounding box object's mesh collision to avoid self collision when generating segments'path")]
[Range(0.0f, 1f)] public float SelfCollisionScale = 0.75f;
// [Tooltip("Checking if pipe segments is inside other collider")]
//[Range(0.0f, 1f)] public float OverlapCheckScale = 0.0f;
[FPD_Header("Extra Conditions")]
[Tooltip("Using this collision mask you can define if pipe segments-path should be near for example to walls, then it will try finding path which is near to wall instead of pipe haning in air")]
public LayerMask HoldMask;
[Tooltip("You can choose directions on which pipe segments should hold on")]
public Vector3[] HoldDirections = new Vector3[] { Vector3.right, -Vector3.right, Vector3.up, -Vector3.up, Vector3.forward, -Vector3.forward };
[Tooltip("How far segments can be to hold mask collision check, beware to not set it too low")]
public float MinimalDistanceToHoldMask = 1.5f;
[FPD_Header("Random Find Desired Position ON START")]
public int RFindSeed = 0;
public LayerMask RFindMask = ~(0 << 0);
public Vector3[] RFindDirections = new Vector3[] { Vector3.right, -Vector3.right, Vector3.up, -Vector3.up, Vector3.forward, -Vector3.forward };
public bool WorldSpaceRFindDirs = true;
public float RFindMinimumDistance = 5f;
public float RFindMaxDistance = 25f;
public bool FlattendRFindNormal = true;
[Range(1, 32)] public int RFindTries = 16;
[Range(1, 24)] public int RFindSteps = 14;
private void Start()
{
if (RFindSeed == 0) RFindSeed = Random.Range(-99999, 99999);
if (GenerateOnStart)
if (AreGeneratedObjects == false)
{
if (DesiredEnding == null )
FindRandomDesiredPoint(RFindSeed);
PipeGenerate();
//StartCoroutine(IEPreviewGenerationDebug());
}
}
public void PipeGenerate()
{
if (AreGeneratedObjects == false)
if (ValidateGenerationCorrectness())
GenerateObjects();
}
public void Generate()
{
if (RFindSeed == 0) RFindSeed = FGenerators.GetRandom(-99999, 999999);
if (DesiredEnding == null)
{
Physics.SyncTransforms();
CustomEndingPosition = null;
FindRandomDesiredPoint(RFindSeed);
if (!ValidateGenerationCorrectness())
{
#if UNITY_EDITOR
if ( UnityEditor.Selection.Contains(gameObject.GetInstanceID()))
UnityEngine.Debug.Log("[Pipe Generator] Can't validate start/end position (can't find attachement points on scene)");
#endif
return;
}
}
else
{
CustomEndingDirection = null;
CustomEndingPosition = null;
}
PipeGenerate();
}
public void IG_CallAfterGenerated() { }
public void PreviewGenerate()
{
if (DesiredEnding == null)
{
int seed = RFindSeed;
if (seed == 0) seed = Random.Range(-99999, 99999);
FindRandomDesiredPoint(seed);
}
else
{
CustomEndingDirection = null;
CustomEndingPosition = null;
}
if (!ValidateGenerationCorrectness()) return;
PipePreviewGeneration();
}
bool ValidateGenerationCorrectness()
{
if (DesiredEnding == null)
{
if (CustomEndingPosition == null) return false;
}
return true;
}
}
}