Files
2026-02-21 16:45:37 +08:00

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();
}
}