// Animancer // Copyright 2020 Kybernetik // #pragma warning disable CS0649 // Field is never assigned to, and will always have its default value. using System.Collections.Generic; using UnityEngine; namespace Animancer.Examples.InverseKinematics { /// /// Spawns a bunch of obstacles and randomises them each time the target moves too far away. /// [AddComponentMenu(Strings.MenuPrefix + "Examples/Inverse Kinematics - Obstacle Treadmill")] [HelpURL(Strings.APIDocumentationURL + ".Examples.InverseKinematics/ObstacleTreadmill")] public sealed class ObstacleTreadmill : MonoBehaviour { /************************************************************************************************************************/ [SerializeField] private float _SpawnCount = 10; [SerializeField] private Material _ObstacleMaterial; [SerializeField] private float _Length; [SerializeField] private float _RotationVariance = 45; [SerializeField] private float _BaseScale = 1; [SerializeField] private float _ScaleVariance = 0.1f; [SerializeField] private Transform _Target; /************************************************************************************************************************/ private readonly List Obstacles = new List(); /************************************************************************************************************************/ private void Awake() { // Spawn a bunch of obstacles and randomise their layout. for (int i = 0; i < _SpawnCount; i++) { var obj = GameObject.CreatePrimitive(PrimitiveType.Capsule).transform; obj.GetComponent().sharedMaterial = _ObstacleMaterial; obj.parent = transform; Obstacles.Add(obj); } ScrambleObjects(); } /************************************************************************************************************************/ private void ScrambleObjects() { // Move and rotate each of the obstacles randomly. for (int i = 0; i < Obstacles.Count; i++) { var obj = Obstacles[i]; obj.localPosition = new Vector3(UnityEngine.Random.Range(0, _Length), 0, 0); obj.localRotation = Quaternion.Euler(90, UnityEngine.Random.Range(-_RotationVariance, _RotationVariance), 0); obj.localScale = Vector3.one * (_BaseScale + UnityEngine.Random.Range(-_ScaleVariance, _ScaleVariance)); } } /************************************************************************************************************************/ private void FixedUpdate() { // When the target moves too far, teleport them back and randomize the obstacles again. var position = _Target.position; if (position.x < transform.position.x) { ScrambleObjects(); position.x += _Length; // Adjust the height to make sure it is above the ground. position.y += 5; RaycastHit raycastHit; if (Physics.Raycast(position, Vector3.down, out raycastHit, 10)) position = raycastHit.point; _Target.position = position; } } /************************************************************************************************************************/ [SerializeField] private Transform _Ground; public float Slope { get { return _Ground.localEulerAngles.z; } set { _Ground.localEulerAngles = new Vector3(0, 0, value); } } /************************************************************************************************************************/ } }