392 lines
10 KiB
C#
392 lines
10 KiB
C#
using System;
|
|
using UnityEngine;
|
|
|
|
public class SchoolChild : MonoBehaviour
|
|
{
|
|
[HideInInspector]
|
|
public SchoolController _spawner;
|
|
|
|
private Vector3 _wayPoint;
|
|
|
|
[HideInInspector]
|
|
public float _speed = 10f;
|
|
|
|
private float _stuckCounter;
|
|
|
|
private float _damping;
|
|
|
|
private Transform _model;
|
|
|
|
public float _targetSpeed;
|
|
|
|
private float tParam;
|
|
|
|
private float _rotateCounterR;
|
|
|
|
private float _rotateCounterL;
|
|
|
|
public Transform _scanner;
|
|
|
|
private bool _scan = true;
|
|
|
|
private bool _instantiated;
|
|
|
|
private static int _updateNextSeed;
|
|
|
|
private int _updateSeed = -1;
|
|
|
|
[HideInInspector]
|
|
public Transform _cacheTransform;
|
|
|
|
[HideInInspector]
|
|
public Guid fishInstanceID;
|
|
|
|
public FishManager.FishKept FishKept;
|
|
|
|
public void Start()
|
|
{
|
|
if (_cacheTransform == null)
|
|
{
|
|
_cacheTransform = base.transform;
|
|
}
|
|
if (_spawner != null)
|
|
{
|
|
LocateRequiredChildren();
|
|
SkewModelForLessUniformedMovement();
|
|
_speed = UnityEngine.Random.Range(_spawner._minSpeed, _spawner._maxSpeed);
|
|
Wander(0f);
|
|
SetRandomWaypoint();
|
|
CheckForBubblesThenInvoke();
|
|
_instantiated = true;
|
|
SetStartPos();
|
|
FrameSkipSeedInit();
|
|
_spawner._activeChildren++;
|
|
}
|
|
else
|
|
{
|
|
base.enabled = false;
|
|
Debug.Log(string.Concat(base.gameObject, " found no school to swim in: ", this, " disabled... Standalone fish not supported, please use the SchoolController"));
|
|
}
|
|
}
|
|
|
|
public void Update()
|
|
{
|
|
if (_spawner._updateDivisor <= 1 || _spawner._updateCounter == _updateSeed)
|
|
{
|
|
CheckForDistanceToWaypoint();
|
|
RotationBasedOnWaypointOrAvoidance();
|
|
ForwardMovement();
|
|
RayCastToPushAwayFromObstacles();
|
|
}
|
|
}
|
|
|
|
public void FrameSkipSeedInit()
|
|
{
|
|
if (_spawner._updateDivisor > 1)
|
|
{
|
|
int num = _spawner._updateDivisor - 1;
|
|
_updateNextSeed++;
|
|
_updateSeed = _updateNextSeed;
|
|
_updateNextSeed %= num;
|
|
}
|
|
}
|
|
|
|
public void CheckForBubblesThenInvoke()
|
|
{
|
|
if (_spawner._bubbles != null)
|
|
{
|
|
InvokeRepeating("EmitBubbles", _spawner._bubbles._emitEverySecond * UnityEngine.Random.value + 1f, _spawner._bubbles._emitEverySecond);
|
|
}
|
|
}
|
|
|
|
public void EmitBubbles()
|
|
{
|
|
_spawner._bubbles.EmitBubbles(_cacheTransform.position, _speed);
|
|
}
|
|
|
|
public void OnDisable()
|
|
{
|
|
CancelInvoke();
|
|
_spawner._activeChildren--;
|
|
}
|
|
|
|
public void OnEnable()
|
|
{
|
|
if (_instantiated)
|
|
{
|
|
CheckForBubblesThenInvoke();
|
|
_spawner._activeChildren++;
|
|
}
|
|
}
|
|
|
|
public void LocateRequiredChildren()
|
|
{
|
|
if (_model == null)
|
|
{
|
|
_model = AquariumUtilities.RecursiveFindChild(_cacheTransform, "ResizeParent");
|
|
}
|
|
if (_scanner == null)
|
|
{
|
|
_scanner = new GameObject().transform;
|
|
_scanner.parent = base.transform;
|
|
_scanner.localRotation = Quaternion.identity;
|
|
_scanner.localPosition = Vector3.zero;
|
|
}
|
|
}
|
|
|
|
public void SkewModelForLessUniformedMovement()
|
|
{
|
|
Quaternion identity = Quaternion.identity;
|
|
identity.eulerAngles = new Vector3(0f, 0f, UnityEngine.Random.Range(0f - _spawner.maxSkew, _spawner.maxSkew));
|
|
_model.rotation = identity;
|
|
}
|
|
|
|
public void SetRandomScale()
|
|
{
|
|
float num = UnityEngine.Random.Range(_spawner._minScale, _spawner._maxScale);
|
|
_cacheTransform.localScale = Vector3.one * num;
|
|
}
|
|
|
|
public void RandomizeStartAnimationFrame()
|
|
{
|
|
foreach (AnimationState item in _model.GetComponent<Animation>())
|
|
{
|
|
item.time = UnityEngine.Random.value * item.length;
|
|
}
|
|
}
|
|
|
|
public void SetStartPos()
|
|
{
|
|
_cacheTransform.position = _wayPoint - new Vector3(0.1f, 0.1f, 0.1f);
|
|
}
|
|
|
|
public Vector3 findWaypoint()
|
|
{
|
|
Vector3 zero = Vector3.zero;
|
|
zero.x = UnityEngine.Random.Range(0f - _spawner._spawnSphere, _spawner._spawnSphere);
|
|
zero.z = UnityEngine.Random.Range(0f - _spawner._spawnSphereDepth, _spawner._spawnSphereDepth);
|
|
zero.y = UnityEngine.Random.Range(0f - _spawner._spawnSphereHeight, _spawner._spawnSphereHeight);
|
|
return zero + _spawner.transform.position;
|
|
}
|
|
|
|
public void RayCastToPushAwayFromObstacles()
|
|
{
|
|
if (_spawner._push)
|
|
{
|
|
RotateScanner();
|
|
RayCastToPushAwayFromObstaclesCheckForCollision();
|
|
}
|
|
}
|
|
|
|
public void RayCastToPushAwayFromObstaclesCheckForCollision()
|
|
{
|
|
RaycastHit hitInfo = default(RaycastHit);
|
|
float num = 0f;
|
|
Vector3 forward = _scanner.forward;
|
|
if (Physics.Raycast(_cacheTransform.position, forward, out hitInfo, _spawner._pushDistance, _spawner._avoidanceMask))
|
|
{
|
|
SchoolChild schoolChild = null;
|
|
schoolChild = hitInfo.transform.GetComponent<SchoolChild>();
|
|
num = (_spawner._pushDistance - hitInfo.distance) / _spawner._pushDistance;
|
|
if (schoolChild != null)
|
|
{
|
|
_cacheTransform.position -= forward * _spawner._newDelta * num * _spawner._pushForce;
|
|
return;
|
|
}
|
|
_speed -= 0.01f * _spawner._newDelta;
|
|
if (_speed < 0.1f)
|
|
{
|
|
_speed = 0.1f;
|
|
}
|
|
_cacheTransform.position -= forward * _spawner._newDelta * num * _spawner._pushForce * 2f;
|
|
_scan = false;
|
|
}
|
|
else
|
|
{
|
|
_scan = true;
|
|
}
|
|
}
|
|
|
|
public void RotateScanner()
|
|
{
|
|
if (_scan)
|
|
{
|
|
_scanner.rotation = UnityEngine.Random.rotation;
|
|
}
|
|
else
|
|
{
|
|
_scanner.Rotate(new Vector3(150f * _spawner._newDelta, 0f, 0f));
|
|
}
|
|
}
|
|
|
|
public bool Avoidance()
|
|
{
|
|
if (!_spawner._avoidance)
|
|
{
|
|
return false;
|
|
}
|
|
RaycastHit hitInfo = default(RaycastHit);
|
|
float num = 0f;
|
|
Quaternion rotation = _cacheTransform.rotation;
|
|
Vector3 eulerAngles = _cacheTransform.rotation.eulerAngles;
|
|
Vector3 forward = _cacheTransform.forward;
|
|
Vector3 right = _cacheTransform.right;
|
|
if (Physics.Raycast(_cacheTransform.position, -Vector3.up + forward * 0.1f, out hitInfo, _spawner._avoidDistance, _spawner._avoidanceMask))
|
|
{
|
|
num = (_spawner._avoidDistance - hitInfo.distance) / _spawner._avoidDistance;
|
|
eulerAngles.x -= _spawner._avoidSpeed * num * _spawner._newDelta * (_speed + 1f);
|
|
rotation.eulerAngles = eulerAngles;
|
|
_cacheTransform.rotation = rotation;
|
|
}
|
|
if (Physics.Raycast(_cacheTransform.position, Vector3.up + forward * 0.1f, out hitInfo, _spawner._avoidDistance, _spawner._avoidanceMask))
|
|
{
|
|
num = (_spawner._avoidDistance - hitInfo.distance) / _spawner._avoidDistance;
|
|
eulerAngles.x += _spawner._avoidSpeed * num * _spawner._newDelta * (_speed + 1f);
|
|
rotation.eulerAngles = eulerAngles;
|
|
_cacheTransform.rotation = rotation;
|
|
}
|
|
if (Physics.Raycast(_cacheTransform.position, forward + right * UnityEngine.Random.Range(-0.1f, 0.1f), out hitInfo, _spawner._stopDistance, _spawner._avoidanceMask))
|
|
{
|
|
num = (_spawner._stopDistance - hitInfo.distance) / _spawner._stopDistance;
|
|
eulerAngles.y -= _spawner._avoidSpeed * num * _spawner._newDelta * (_targetSpeed + 3f);
|
|
rotation.eulerAngles = eulerAngles;
|
|
_cacheTransform.rotation = rotation;
|
|
_speed -= num * _spawner._newDelta * _spawner._stopSpeedMultiplier * _speed;
|
|
if (_speed < 0.01f)
|
|
{
|
|
_speed = 0.01f;
|
|
}
|
|
return true;
|
|
}
|
|
if (Physics.Raycast(_cacheTransform.position, forward + right * (_spawner._avoidAngle + _rotateCounterL), out hitInfo, _spawner._avoidDistance, _spawner._avoidanceMask))
|
|
{
|
|
num = (_spawner._avoidDistance - hitInfo.distance) / _spawner._avoidDistance;
|
|
_rotateCounterL += 0.1f;
|
|
eulerAngles.y -= _spawner._avoidSpeed * num * _spawner._newDelta * _rotateCounterL * (_speed + 1f);
|
|
rotation.eulerAngles = eulerAngles;
|
|
_cacheTransform.rotation = rotation;
|
|
if (_rotateCounterL > 1.5f)
|
|
{
|
|
_rotateCounterL = 1.5f;
|
|
}
|
|
_rotateCounterR = 0f;
|
|
return true;
|
|
}
|
|
if (Physics.Raycast(_cacheTransform.position, forward + right * (0f - (_spawner._avoidAngle + _rotateCounterR)), out hitInfo, _spawner._avoidDistance, _spawner._avoidanceMask))
|
|
{
|
|
num = (_spawner._avoidDistance - hitInfo.distance) / _spawner._avoidDistance;
|
|
if (hitInfo.point.y < _cacheTransform.position.y)
|
|
{
|
|
eulerAngles.y -= _spawner._avoidSpeed * num * _spawner._newDelta * (_speed + 1f);
|
|
}
|
|
else
|
|
{
|
|
eulerAngles.x += _spawner._avoidSpeed * num * _spawner._newDelta * (_speed + 1f);
|
|
}
|
|
_rotateCounterR += 0.1f;
|
|
eulerAngles.y += _spawner._avoidSpeed * num * _spawner._newDelta * _rotateCounterR * (_speed + 1f);
|
|
rotation.eulerAngles = eulerAngles;
|
|
_cacheTransform.rotation = rotation;
|
|
if (_rotateCounterR > 1.5f)
|
|
{
|
|
_rotateCounterR = 1.5f;
|
|
}
|
|
_rotateCounterL = 0f;
|
|
return true;
|
|
}
|
|
_rotateCounterL = 0f;
|
|
_rotateCounterR = 0f;
|
|
return false;
|
|
}
|
|
|
|
public void ForwardMovement()
|
|
{
|
|
_cacheTransform.position += _cacheTransform.TransformDirection(Vector3.forward) * _speed * _spawner._newDelta;
|
|
if (tParam < 1f)
|
|
{
|
|
if (_speed > _targetSpeed)
|
|
{
|
|
tParam += _spawner._newDelta * _spawner._acceleration;
|
|
}
|
|
else
|
|
{
|
|
tParam += _spawner._newDelta * _spawner._brake;
|
|
}
|
|
_speed = Mathf.Lerp(_speed, _targetSpeed, tParam);
|
|
}
|
|
}
|
|
|
|
public void RotationBasedOnWaypointOrAvoidance()
|
|
{
|
|
Quaternion identity = Quaternion.identity;
|
|
identity = Quaternion.LookRotation(_wayPoint - _cacheTransform.position);
|
|
if (!Avoidance())
|
|
{
|
|
_cacheTransform.rotation = Quaternion.Slerp(_cacheTransform.rotation, identity, _spawner._newDelta * _damping);
|
|
}
|
|
float x = _cacheTransform.localEulerAngles.x;
|
|
x = ((!(x > 180f)) ? x : (x - 360f));
|
|
Quaternion rotation = _cacheTransform.rotation;
|
|
Vector3 eulerAngles = rotation.eulerAngles;
|
|
eulerAngles.x = ClampAngle(x, -50f, 50f);
|
|
rotation.eulerAngles = eulerAngles;
|
|
_cacheTransform.rotation = rotation;
|
|
}
|
|
|
|
public void CheckForDistanceToWaypoint()
|
|
{
|
|
if ((_cacheTransform.position - _wayPoint).magnitude < _spawner._waypointDistance + _stuckCounter)
|
|
{
|
|
Wander(0f);
|
|
_stuckCounter = 0f;
|
|
CheckIfThisShouldTriggerNewFlockWaypoint();
|
|
}
|
|
else
|
|
{
|
|
_stuckCounter += _spawner._newDelta * (_spawner._waypointDistance * 0.25f);
|
|
}
|
|
}
|
|
|
|
public void CheckIfThisShouldTriggerNewFlockWaypoint()
|
|
{
|
|
if (_spawner._childTriggerPos)
|
|
{
|
|
_spawner.SetRandomWaypointPosition();
|
|
}
|
|
}
|
|
|
|
public static float ClampAngle(float angle, float min, float max)
|
|
{
|
|
if (angle < -360f)
|
|
{
|
|
angle += 360f;
|
|
}
|
|
if (angle > 360f)
|
|
{
|
|
angle -= 360f;
|
|
}
|
|
return Mathf.Clamp(angle, min, max);
|
|
}
|
|
|
|
public void SetAnimationSpeed()
|
|
{
|
|
foreach (AnimationState item in _model.GetComponent<Animation>())
|
|
{
|
|
item.speed = UnityEngine.Random.Range(_spawner._minAnimationSpeed, _spawner._maxAnimationSpeed) * _spawner._schoolSpeed * _speed + 0.1f;
|
|
}
|
|
}
|
|
|
|
public void Wander(float delay)
|
|
{
|
|
_damping = UnityEngine.Random.Range(_spawner._minDamping, _spawner._maxDamping);
|
|
_targetSpeed = UnityEngine.Random.Range(_spawner._minSpeed, _spawner._maxSpeed) * _spawner._speedCurveMultiplier.Evaluate(UnityEngine.Random.value) * _spawner._schoolSpeed;
|
|
Invoke("SetRandomWaypoint", delay);
|
|
}
|
|
|
|
public void SetRandomWaypoint()
|
|
{
|
|
tParam = 0f;
|
|
_wayPoint = findWaypoint();
|
|
}
|
|
}
|