Essentials + extra crap
Loadings Startups Movement Camera
This commit is contained in:
1 parent
662f4a1d05
commit
5f5ace1b52
734 files changed
+107323
-1713
No files matched your search
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3487788d480845039f84f7aa89195d0b
|
||||
timeCreated: 1765564013
|
||||
@@ -1,19 +0,0 @@
|
||||
using Reflex.Core;
|
||||
|
||||
namespace Code.Debug
|
||||
{
|
||||
public class DebugInstaller : IInstaller
|
||||
{
|
||||
public void InstallBindings(ContainerBuilder containerBuilder)
|
||||
{
|
||||
containerBuilder.AddSingleton(typeof(DebugStateMachine));
|
||||
|
||||
containerBuilder.OnContainerBuilt += Bootstrap;
|
||||
}
|
||||
|
||||
private void Bootstrap(Container container)
|
||||
{
|
||||
container.Resolve<DebugStateMachine>();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 35352cf8cf4f4b638e1a1693a704f052
|
||||
timeCreated: 1765565958
|
||||
@@ -1,20 +0,0 @@
|
||||
using System;
|
||||
using Code.StateMachine;
|
||||
|
||||
namespace Code.Debug
|
||||
{
|
||||
public enum DebugStates
|
||||
{
|
||||
First,
|
||||
Second,
|
||||
Third
|
||||
}
|
||||
public class DebugStateMachineContext
|
||||
{
|
||||
public int SomeValue;
|
||||
}
|
||||
|
||||
[Generators.StateMachine(typeof(DebugStateMachineContext), typeof(DebugStates))]
|
||||
public partial class DebugStateMachine
|
||||
{ }
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 71d501bd1540463496c6df3fa0bbb0ca
|
||||
timeCreated: 1765564028
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6e84c82fd2ce4c449bee71acf27ed874
|
||||
timeCreated: 1765566284
|
||||
@@ -1,24 +0,0 @@
|
||||
using Code.Generators;
|
||||
using Code.StateMachine;
|
||||
|
||||
namespace Code.Debug.States
|
||||
{
|
||||
[State(typeof(DebugStateMachineContext) )]
|
||||
public partial class FirstState : BaseState<DebugStates, DebugStateMachineContext>
|
||||
{
|
||||
public FirstState(DebugStateMachineContext context) : base(context)
|
||||
{
|
||||
}
|
||||
|
||||
public override DebugStates myState => DebugStates.First;
|
||||
}
|
||||
[State(typeof(DebugStateMachineContext) )]
|
||||
public partial class SecondState : BaseState<DebugStates, DebugStateMachineContext>
|
||||
{
|
||||
public SecondState(DebugStateMachineContext context) : base(context)
|
||||
{
|
||||
}
|
||||
|
||||
public override DebugStates myState => DebugStates.First;
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 24af5a4d2545481589242a5945bbafa5
|
||||
timeCreated: 1765566292
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 07cf07a937934e0094469237b5865b60
|
||||
timeCreated: 1766350980
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b03c560586d24e78b3fee9249e2f3d61
|
||||
timeCreated: 1766605332
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b44837d95edd481087730e30635ab5fc
|
||||
timeCreated: 1766605342
|
||||
@@ -0,0 +1,483 @@
|
||||
using System.Collections.Generic;
|
||||
using KinematicCharacterController;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Code.Example.Liminal.Character
|
||||
{
|
||||
public enum CharacterState
|
||||
{
|
||||
Default,
|
||||
}
|
||||
|
||||
public enum OrientationMethod
|
||||
{
|
||||
TowardsCamera,
|
||||
TowardsMovement,
|
||||
}
|
||||
|
||||
public class PlayerCharacterInputs
|
||||
{
|
||||
public float MoveAxisForward;
|
||||
public float MoveAxisRight;
|
||||
public Quaternion CameraRotation;
|
||||
public bool CrouchDown;
|
||||
public bool CrouchUp;
|
||||
}
|
||||
|
||||
public struct AICharacterInputs
|
||||
{
|
||||
public Vector3 MoveVector;
|
||||
public Vector3 LookVector;
|
||||
}
|
||||
|
||||
public enum BonusOrientationMethod
|
||||
{
|
||||
None,
|
||||
TowardsGravity,
|
||||
TowardsGroundSlopeAndGravity,
|
||||
}
|
||||
|
||||
public class LiminalCharacterController : MonoBehaviour, ICharacterController
|
||||
{
|
||||
public KinematicCharacterMotor Motor;
|
||||
|
||||
[Header("Stable Movement")] public float MaxStableMoveSpeed = 10f;
|
||||
public float StableMovementSharpness = 15f;
|
||||
public float OrientationSharpness = 10f;
|
||||
public bool InfinitelySharpRotation;
|
||||
public OrientationMethod OrientationMethod = OrientationMethod.TowardsCamera;
|
||||
|
||||
[Header("Air Movement")] public float MaxAirMoveSpeed = 15f;
|
||||
public float AirAccelerationSpeed = 15f;
|
||||
public float Drag = 0.1f;
|
||||
|
||||
[Header("Misc")] public List<Collider> IgnoredColliders = new List<Collider>();
|
||||
public BonusOrientationMethod BonusOrientationMethod = BonusOrientationMethod.None;
|
||||
public float BonusOrientationSharpness = 10f;
|
||||
|
||||
public Vector3 Gravity = new Vector3(0, -30f, 0);
|
||||
|
||||
// public Transform MeshRoot;
|
||||
public float CrouchedCapsuleHeight = 1f;
|
||||
|
||||
public CharacterState CurrentCharacterState { get; private set; }
|
||||
|
||||
private Collider[] _probedColliders = new Collider[8];
|
||||
private RaycastHit[] _probedHits = new RaycastHit[8];
|
||||
private Vector3 _moveInputVector;
|
||||
private Vector3 _lookInputVector;
|
||||
private Vector3 _internalVelocityAdd = Vector3.zero;
|
||||
private bool _shouldBeCrouching = false;
|
||||
private bool _isCrouching = false;
|
||||
|
||||
|
||||
public void Teleport(Vector3 position, Quaternion rotation)
|
||||
{
|
||||
Motor.SetPosition(position);
|
||||
Motor.SetRotation(rotation);
|
||||
}
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
// Handle initial state
|
||||
TransitionToState(CharacterState.Default);
|
||||
|
||||
// Assign the characterController to the motor
|
||||
Motor.CharacterController = this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles movement state transitions and enter/exit callbacks
|
||||
/// </summary>
|
||||
public void TransitionToState(CharacterState newState)
|
||||
{
|
||||
CharacterState tmpInitialState = CurrentCharacterState;
|
||||
OnStateExit(tmpInitialState, newState);
|
||||
CurrentCharacterState = newState;
|
||||
OnStateEnter(newState, tmpInitialState);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event when entering a state
|
||||
/// </summary>
|
||||
private void OnStateEnter(CharacterState state, CharacterState fromState)
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case CharacterState.Default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event when exiting a state
|
||||
/// </summary>
|
||||
private void OnStateExit(CharacterState state, CharacterState toState)
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case CharacterState.Default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is called every frame by ExamplePlayer in order to tell the character what its inputs are
|
||||
/// </summary>
|
||||
public void SetInputs(PlayerCharacterInputs inputs)
|
||||
{
|
||||
// Clamp input
|
||||
Vector3 moveInputVector =
|
||||
Vector3.ClampMagnitude(new Vector3(inputs.MoveAxisRight, 0f, inputs.MoveAxisForward), 1f);
|
||||
|
||||
// Calculate camera direction and rotation on the character plane
|
||||
Vector3 cameraPlanarDirection =
|
||||
Vector3.ProjectOnPlane(inputs.CameraRotation * Vector3.forward, Motor.CharacterUp).normalized;
|
||||
if (cameraPlanarDirection.sqrMagnitude == 0f)
|
||||
{
|
||||
cameraPlanarDirection = Vector3.ProjectOnPlane(inputs.CameraRotation * Vector3.up, Motor.CharacterUp)
|
||||
.normalized;
|
||||
}
|
||||
|
||||
Quaternion cameraPlanarRotation = Quaternion.LookRotation(cameraPlanarDirection, Motor.CharacterUp);
|
||||
|
||||
switch (CurrentCharacterState)
|
||||
{
|
||||
case CharacterState.Default:
|
||||
{
|
||||
// Move and look inputs
|
||||
_moveInputVector = cameraPlanarRotation * moveInputVector;
|
||||
|
||||
switch (OrientationMethod)
|
||||
{
|
||||
case OrientationMethod.TowardsCamera:
|
||||
_lookInputVector = cameraPlanarDirection;
|
||||
break;
|
||||
case OrientationMethod.TowardsMovement:
|
||||
_lookInputVector = _moveInputVector.normalized;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// Crouching input
|
||||
if (inputs.CrouchDown)
|
||||
{
|
||||
_shouldBeCrouching = true;
|
||||
|
||||
if (!_isCrouching)
|
||||
{
|
||||
_isCrouching = true;
|
||||
Motor.SetCapsuleDimensions(0.5f, CrouchedCapsuleHeight, CrouchedCapsuleHeight * 0.5f);
|
||||
// MeshRoot.localScale = new Vector3(1f, 0.5f, 1f);
|
||||
}
|
||||
}
|
||||
else if (inputs.CrouchUp)
|
||||
{
|
||||
_shouldBeCrouching = false;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is called every frame by the AI script in order to tell the character what its inputs are
|
||||
/// </summary>
|
||||
public void SetInputs(ref AICharacterInputs inputs)
|
||||
{
|
||||
_moveInputVector = inputs.MoveVector;
|
||||
_lookInputVector = inputs.LookVector;
|
||||
}
|
||||
|
||||
private Quaternion _tmpTransientRot;
|
||||
|
||||
/// <summary>
|
||||
/// (Called by KinematicCharacterMotor during its update cycle)
|
||||
/// This is called before the character begins its movement update
|
||||
/// </summary>
|
||||
public void BeforeCharacterUpdate(float deltaTime)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// (Called by KinematicCharacterMotor during its update cycle)
|
||||
/// This is where you tell your character what its rotation should be right now.
|
||||
/// This is the ONLY place where you should set the character's rotation
|
||||
/// </summary>
|
||||
public void UpdateRotation(ref Quaternion currentRotation, float deltaTime)
|
||||
{
|
||||
switch (CurrentCharacterState)
|
||||
{
|
||||
case CharacterState.Default:
|
||||
{
|
||||
if (!InfinitelySharpRotation)
|
||||
{
|
||||
if (_lookInputVector.sqrMagnitude > 0f && OrientationSharpness > 0f)
|
||||
{
|
||||
// Smoothly interpolate from current to target look direction
|
||||
Vector3 smoothedLookInputDirection = Vector3.Slerp(Motor.CharacterForward,
|
||||
_lookInputVector, 1 - Mathf.Exp(-OrientationSharpness * deltaTime)).normalized;
|
||||
|
||||
// Set the current rotation (which will be used by the KinematicCharacterMotor)
|
||||
currentRotation =
|
||||
Quaternion.LookRotation(smoothedLookInputDirection, Motor.CharacterUp);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
currentRotation = Quaternion.LookRotation(_lookInputVector, Motor.CharacterUp);
|
||||
}
|
||||
|
||||
Vector3 currentUp = (currentRotation * Vector3.up);
|
||||
if (BonusOrientationMethod == BonusOrientationMethod.TowardsGravity)
|
||||
{
|
||||
// Rotate from current up to invert gravity
|
||||
Vector3 smoothedGravityDir = Vector3.Slerp(currentUp, -Gravity.normalized,
|
||||
1 - Mathf.Exp(-BonusOrientationSharpness * deltaTime));
|
||||
currentRotation = Quaternion.FromToRotation(currentUp, smoothedGravityDir) * currentRotation;
|
||||
}
|
||||
else if (BonusOrientationMethod == BonusOrientationMethod.TowardsGroundSlopeAndGravity)
|
||||
{
|
||||
if (Motor.GroundingStatus.IsStableOnGround)
|
||||
{
|
||||
Vector3 initialCharacterBottomHemiCenter =
|
||||
Motor.TransientPosition + (currentUp * Motor.Capsule.radius);
|
||||
|
||||
Vector3 smoothedGroundNormal = Vector3.Slerp(Motor.CharacterUp,
|
||||
Motor.GroundingStatus.GroundNormal,
|
||||
1 - Mathf.Exp(-BonusOrientationSharpness * deltaTime));
|
||||
currentRotation = Quaternion.FromToRotation(currentUp, smoothedGroundNormal) *
|
||||
currentRotation;
|
||||
|
||||
// Move the position to create a rotation around the bottom hemi center instead of around the pivot
|
||||
Motor.SetTransientPosition(initialCharacterBottomHemiCenter +
|
||||
(currentRotation * Vector3.down * Motor.Capsule.radius));
|
||||
}
|
||||
else
|
||||
{
|
||||
Vector3 smoothedGravityDir = Vector3.Slerp(currentUp, -Gravity.normalized,
|
||||
1 - Mathf.Exp(-BonusOrientationSharpness * deltaTime));
|
||||
currentRotation = Quaternion.FromToRotation(currentUp, smoothedGravityDir) *
|
||||
currentRotation;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Vector3 smoothedGravityDir = Vector3.Slerp(currentUp, Vector3.up,
|
||||
1 - Mathf.Exp(-BonusOrientationSharpness * deltaTime));
|
||||
currentRotation = Quaternion.FromToRotation(currentUp, smoothedGravityDir) * currentRotation;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// (Called by KinematicCharacterMotor during its update cycle)
|
||||
/// This is where you tell your character what its velocity should be right now.
|
||||
/// This is the ONLY place where you can set the character's velocity
|
||||
/// </summary>
|
||||
public void UpdateVelocity(ref Vector3 currentVelocity, float deltaTime)
|
||||
{
|
||||
switch (CurrentCharacterState)
|
||||
{
|
||||
case CharacterState.Default:
|
||||
{
|
||||
// Ground movement
|
||||
if (Motor.GroundingStatus.IsStableOnGround)
|
||||
{
|
||||
float currentVelocityMagnitude = currentVelocity.magnitude;
|
||||
|
||||
Vector3 effectiveGroundNormal = Motor.GroundingStatus.GroundNormal;
|
||||
|
||||
// Reorient velocity on slope
|
||||
currentVelocity = Motor.GetDirectionTangentToSurface(currentVelocity, effectiveGroundNormal) *
|
||||
currentVelocityMagnitude;
|
||||
|
||||
// Calculate target velocity
|
||||
Vector3 inputRight = Vector3.Cross(_moveInputVector, Motor.CharacterUp);
|
||||
Vector3 reorientedInput = Vector3.Cross(effectiveGroundNormal, inputRight).normalized *
|
||||
_moveInputVector.magnitude;
|
||||
Vector3 targetMovementVelocity = reorientedInput * MaxStableMoveSpeed;
|
||||
|
||||
// Smooth movement Velocity
|
||||
currentVelocity = Vector3.Lerp(currentVelocity, targetMovementVelocity,
|
||||
1f - Mathf.Exp(-StableMovementSharpness * deltaTime));
|
||||
}
|
||||
// Air movement
|
||||
else
|
||||
{
|
||||
// Add move input
|
||||
if (_moveInputVector.sqrMagnitude > 0f)
|
||||
{
|
||||
Vector3 addedVelocity = _moveInputVector * AirAccelerationSpeed * deltaTime;
|
||||
|
||||
Vector3 currentVelocityOnInputsPlane =
|
||||
Vector3.ProjectOnPlane(currentVelocity, Motor.CharacterUp);
|
||||
|
||||
// Limit air velocity from inputs
|
||||
if (currentVelocityOnInputsPlane.magnitude < MaxAirMoveSpeed)
|
||||
{
|
||||
// clamp addedVel to make total vel not exceed max vel on inputs plane
|
||||
Vector3 newTotal = Vector3.ClampMagnitude(currentVelocityOnInputsPlane + addedVelocity,
|
||||
MaxAirMoveSpeed);
|
||||
addedVelocity = newTotal - currentVelocityOnInputsPlane;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Make sure added vel doesn't go in the direction of the already-exceeding velocity
|
||||
if (Vector3.Dot(currentVelocityOnInputsPlane, addedVelocity) > 0f)
|
||||
{
|
||||
addedVelocity = Vector3.ProjectOnPlane(addedVelocity,
|
||||
currentVelocityOnInputsPlane.normalized);
|
||||
}
|
||||
}
|
||||
|
||||
// Prevent air-climbing sloped walls
|
||||
if (Motor.GroundingStatus.FoundAnyGround)
|
||||
{
|
||||
if (Vector3.Dot(currentVelocity + addedVelocity, addedVelocity) > 0f)
|
||||
{
|
||||
Vector3 perpenticularObstructionNormal = Vector3
|
||||
.Cross(Vector3.Cross(Motor.CharacterUp, Motor.GroundingStatus.GroundNormal),
|
||||
Motor.CharacterUp).normalized;
|
||||
addedVelocity =
|
||||
Vector3.ProjectOnPlane(addedVelocity, perpenticularObstructionNormal);
|
||||
}
|
||||
}
|
||||
|
||||
// Apply added velocity
|
||||
currentVelocity += addedVelocity;
|
||||
}
|
||||
|
||||
// Gravity
|
||||
currentVelocity += Gravity * deltaTime;
|
||||
|
||||
// Drag
|
||||
currentVelocity *= (1f / (1f + (Drag * deltaTime)));
|
||||
}
|
||||
|
||||
// Take into account additive velocity
|
||||
if (_internalVelocityAdd.sqrMagnitude > 0f)
|
||||
{
|
||||
currentVelocity += _internalVelocityAdd;
|
||||
_internalVelocityAdd = Vector3.zero;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// (Called by KinematicCharacterMotor during its update cycle)
|
||||
/// This is called after the character has finished its movement update
|
||||
/// </summary>
|
||||
public void AfterCharacterUpdate(float deltaTime)
|
||||
{
|
||||
switch (CurrentCharacterState)
|
||||
{
|
||||
case CharacterState.Default:
|
||||
{
|
||||
// Handle uncrouching
|
||||
if (_isCrouching && !_shouldBeCrouching)
|
||||
{
|
||||
// Do an overlap test with the character's standing height to see if there are any obstructions
|
||||
Motor.SetCapsuleDimensions(0.5f, 2f, 1f);
|
||||
if (Motor.CharacterOverlap(
|
||||
Motor.TransientPosition,
|
||||
Motor.TransientRotation,
|
||||
_probedColliders,
|
||||
Motor.CollidableLayers,
|
||||
QueryTriggerInteraction.Ignore) > 0)
|
||||
{
|
||||
// If obstructions, just stick to crouching dimensions
|
||||
Motor.SetCapsuleDimensions(0.5f, CrouchedCapsuleHeight, CrouchedCapsuleHeight * 0.5f);
|
||||
}
|
||||
else
|
||||
{
|
||||
// If no obstructions, uncrouch
|
||||
// MeshRoot.localScale = new Vector3(1f, 1f, 1f);
|
||||
_isCrouching = false;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void PostGroundingUpdate(float deltaTime)
|
||||
{
|
||||
// Handle landing and leaving ground
|
||||
if (Motor.GroundingStatus.IsStableOnGround && !Motor.LastGroundingStatus.IsStableOnGround)
|
||||
{
|
||||
OnLanded();
|
||||
}
|
||||
else if (!Motor.GroundingStatus.IsStableOnGround && Motor.LastGroundingStatus.IsStableOnGround)
|
||||
{
|
||||
OnLeaveStableGround();
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsColliderValidForCollisions(Collider coll)
|
||||
{
|
||||
if (IgnoredColliders.Count == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (IgnoredColliders.Contains(coll))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void OnGroundHit(Collider hitCollider, Vector3 hitNormal, Vector3 hitPoint,
|
||||
ref HitStabilityReport hitStabilityReport)
|
||||
{
|
||||
}
|
||||
|
||||
public void OnMovementHit(Collider hitCollider, Vector3 hitNormal, Vector3 hitPoint,
|
||||
ref HitStabilityReport hitStabilityReport)
|
||||
{
|
||||
}
|
||||
|
||||
public void AddVelocity(Vector3 velocity)
|
||||
{
|
||||
switch (CurrentCharacterState)
|
||||
{
|
||||
case CharacterState.Default:
|
||||
{
|
||||
_internalVelocityAdd += velocity;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void ProcessHitStabilityReport(Collider hitCollider, Vector3 hitNormal, Vector3 hitPoint,
|
||||
Vector3 atCharacterPosition, Quaternion atCharacterRotation, ref HitStabilityReport hitStabilityReport)
|
||||
{
|
||||
}
|
||||
|
||||
protected void OnLanded()
|
||||
{
|
||||
}
|
||||
|
||||
protected void OnLeaveStableGround()
|
||||
{
|
||||
}
|
||||
|
||||
public void OnDiscreteCollisionDetected(Collider hitCollider)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ba1cb0200be742ec8d680ad8b2d662cb
|
||||
timeCreated: 1766610552
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d7569a6973424ff5802b1635c5338316
|
||||
timeCreated: 1766611137
|
||||
@@ -0,0 +1,18 @@
|
||||
using KinematicCharacterController;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Code.Example.Liminal.Player
|
||||
{
|
||||
public class PlayerAnimator : MonoBehaviour
|
||||
{
|
||||
private static readonly int Velocity = Animator.StringToHash("Velocity");
|
||||
|
||||
[SerializeField] private Animator animator;
|
||||
[SerializeField] private KinematicCharacterMotor characterMotor;
|
||||
|
||||
private void Update()
|
||||
{
|
||||
animator.SetFloat(Velocity, characterMotor.Velocity.magnitude);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e79636518658432a99481e476aeebc66
|
||||
timeCreated: 1766610269
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace Code.Example.Liminal.Player
|
||||
{
|
||||
public class PlayerFactory
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 60b7c1aa1c8c4189a2b442d2b4c628eb
|
||||
timeCreated: 1766652945
|
||||
@@ -0,0 +1,74 @@
|
||||
using System;
|
||||
using Code.Example.Liminal.Character;
|
||||
using Code.Infrastructure.Camera;
|
||||
using Code.Infrastructure.Camera.CameraStates;
|
||||
using Code.Infrastructure.Input;
|
||||
using Reflex.Attributes;
|
||||
using UnityEngine;
|
||||
using UnityEngine.InputSystem;
|
||||
|
||||
namespace Code.Example.Liminal.Player
|
||||
{
|
||||
public class PlayerMovementController : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private LiminalCharacterController characterController;
|
||||
private PlayerCharacterInputs _currentInputs = new();
|
||||
private IInputService _inputService;
|
||||
|
||||
private CameraStateMachine _cameraStateMachine;
|
||||
|
||||
public Transform PlayerHeadPoint;
|
||||
|
||||
[Inject]
|
||||
private void Construct(IInputService inputService, CameraStateMachine stateMachine)
|
||||
{
|
||||
_inputService = inputService;
|
||||
_inputService.BindActionPerformed((int) ActionMappings.Gameplay, (int) GameplayActions.Move, OnMovePerformed);
|
||||
_inputService.BindActionCancel((int) ActionMappings.Gameplay, (int) GameplayActions.Move, OnMoveCanceled);
|
||||
_inputService.BindActionPerformed((int) ActionMappings.Gameplay, (int) GameplayActions.Crouch, OnCrouchPerformed);
|
||||
_inputService.BindActionCancel((int) ActionMappings.Gameplay, (int) GameplayActions.Crouch, OnCrouchCanceled);
|
||||
|
||||
_cameraStateMachine = stateMachine;
|
||||
((FirstPersonCameraState)stateMachine.CurrentBaseState).SetPlayer(this);
|
||||
|
||||
}
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
_currentInputs.MoveAxisForward = 0;
|
||||
_currentInputs.MoveAxisRight = 0;
|
||||
_currentInputs.CrouchUp = true;
|
||||
_currentInputs.CrouchDown = false;
|
||||
_currentInputs.CameraRotation = Quaternion.identity;
|
||||
}
|
||||
|
||||
public void SetCameraRotation(Quaternion rotation) => _currentInputs.CameraRotation = rotation;
|
||||
private void OnMovePerformed(InputAction.CallbackContext context)
|
||||
{
|
||||
_currentInputs.MoveAxisForward = context.ReadValue<Vector2>().y;
|
||||
_currentInputs.MoveAxisRight = context.ReadValue<Vector2>().x;
|
||||
}
|
||||
|
||||
private void OnMoveCanceled(InputAction.CallbackContext context)
|
||||
{
|
||||
_currentInputs.MoveAxisForward = 0;
|
||||
_currentInputs.MoveAxisRight = 0;
|
||||
}
|
||||
|
||||
private void OnCrouchPerformed(InputAction.CallbackContext context)
|
||||
{
|
||||
_currentInputs.CrouchDown = true;
|
||||
_currentInputs.CrouchUp = false;
|
||||
}
|
||||
|
||||
private void OnCrouchCanceled(InputAction.CallbackContext context)
|
||||
{
|
||||
_currentInputs.CrouchUp = true;
|
||||
_currentInputs.CrouchDown = false;
|
||||
}
|
||||
private void Update()
|
||||
{
|
||||
characterController.SetInputs(_currentInputs);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8dd688d33c434f999d0ff7cd0553f1ee
|
||||
timeCreated: 1766611089
|
||||
@@ -1,26 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Code.Generators
|
||||
{
|
||||
public class StateMachine : Attribute
|
||||
{
|
||||
public Type StateMachineContextType;
|
||||
public Type StateMachineEnumType;
|
||||
|
||||
public StateMachine(Type stateMachineContextType, Type stateMachineEnumType)
|
||||
{
|
||||
StateMachineContextType = stateMachineContextType;
|
||||
StateMachineEnumType = stateMachineEnumType;
|
||||
}
|
||||
}
|
||||
|
||||
public class State : Attribute
|
||||
{
|
||||
public Type StateMachineContextType;
|
||||
public State (Type stateMachineContextType )
|
||||
{
|
||||
StateMachineContextType = stateMachineContextType;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8ae0afd22327405eb4098d4106118b68
|
||||
timeCreated: 1766056068
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 378d32559e654d4b91e761f7f5d4cee6
|
||||
timeCreated: 1765572320
|
||||
@@ -0,0 +1,25 @@
|
||||
using Code.Infrastructure.Camera;
|
||||
using Reflex.Attributes;
|
||||
|
||||
namespace Code.Infrastructure.App
|
||||
{
|
||||
public enum AppStates
|
||||
{
|
||||
Bootstrap,
|
||||
Gameplay,
|
||||
MainMenu
|
||||
}
|
||||
|
||||
public class AppStateMachineContext
|
||||
{
|
||||
[Inject] public SceneLoader.SceneLoader SceneLoader { get; set; }
|
||||
[Inject] public CameraStateMachine Camera { get; set; }
|
||||
}
|
||||
|
||||
[Generators.StateMachine(typeof(AppStateMachineContext),typeof(AppStates))]
|
||||
public partial class AppStateMachine
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5627248405434f028be921cb7916f823
|
||||
timeCreated: 1765572329
|
||||
@@ -0,0 +1,69 @@
|
||||
using Code.Infrastructure.Camera;
|
||||
using Code.Infrastructure.Configs;
|
||||
using Code.Infrastructure.Input;
|
||||
using Code.Infrastructure.Loadings;
|
||||
using Code.Infrastructure.SceneLoader;
|
||||
using Reflex.Core;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Code.Infrastructure.App
|
||||
{
|
||||
public class PapaInstaller : MonoBehaviour, IInstaller, ISceneConfigsLoadedHandle, IInputServiceInitializedHandle, ICameraInitializedHandle
|
||||
{
|
||||
public void InstallBindings(ContainerBuilder containerBuilder)
|
||||
{
|
||||
containerBuilder.AddSingleton(typeof(EventBus.EventBus));
|
||||
containerBuilder.AddSingleton(typeof(ConfigLocator), typeof(IConfigLocator));
|
||||
containerBuilder.AddSingleton(typeof(SceneLoader.SceneLoader));
|
||||
containerBuilder.AddSingleton(typeof(InputService),typeof(IInputService));
|
||||
|
||||
containerBuilder.OnContainerBuilt += Bootstrap;
|
||||
|
||||
containerBuilder.AddSingleton(typeof(AppStateMachine));
|
||||
containerBuilder.AddSingleton(typeof(AppStateMachineContext));
|
||||
|
||||
containerBuilder.AddSingleton(typeof(CameraFactory));
|
||||
containerBuilder.AddSingleton(typeof(CameraStateMachine));
|
||||
containerBuilder.AddSingleton(typeof(CameraStateMachineContext));
|
||||
|
||||
}
|
||||
|
||||
private Loading initialLoading;
|
||||
private Container _thatRightContainer;
|
||||
private void Bootstrap(Container container)
|
||||
{
|
||||
_thatRightContainer = container;
|
||||
|
||||
container.Resolve<EventBus.EventBus>().Subscribe(this);
|
||||
container.Resolve<SceneLoader.SceneLoader>();
|
||||
container.Resolve<IInputService>();
|
||||
container.Resolve<CameraFactory>().CreateCameraStateMachine(container.Resolve<CameraStateMachine>()).Forget();
|
||||
|
||||
initialLoading = new Loading(3, () => EssentialLoadEnded(container));
|
||||
}
|
||||
|
||||
private void EssentialLoadEnded(Container container)
|
||||
{
|
||||
container.Resolve<AppStateMachine>().SwitchState(AppStates.Bootstrap).AllowStateTransition(AppStates.Gameplay);
|
||||
container.Resolve<EventBus.EventBus>().Unsubscribe(this);
|
||||
}
|
||||
|
||||
public void SceneConfigsLoaded()
|
||||
{
|
||||
initialLoading.DoProgress();
|
||||
}
|
||||
|
||||
public void InputServiceInitialized()
|
||||
{
|
||||
initialLoading.DoProgress();
|
||||
}
|
||||
|
||||
public void CameraInitialized(CameraStateMachineContext.CameraLoadedData data)
|
||||
{
|
||||
_thatRightContainer.Resolve<CameraStateMachineContext>().cameraLoadedData = data;
|
||||
_thatRightContainer.Resolve<CameraStateMachine>().SwitchState(CameraMode.None)
|
||||
.AllowStateTransition(CameraMode.FirstPerson);
|
||||
initialLoading.DoProgress();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e62d9c9e01334727887a684e008440a6
|
||||
timeCreated: 1765572590
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 30a683bd88f74628b64f7e17315b0c5d
|
||||
timeCreated: 1766393607
|
||||
@@ -0,0 +1,19 @@
|
||||
using Reflex.Core;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Code.Infrastructure.App.SceneInstallers
|
||||
{
|
||||
public class GameplaySceneInstaller : MonoBehaviour, IInstaller
|
||||
{
|
||||
public void InstallBindings(ContainerBuilder containerBuilder)
|
||||
{
|
||||
|
||||
containerBuilder.OnContainerBuilt += PostInstall;
|
||||
}
|
||||
|
||||
private void PostInstall(Container container)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ab7d8da1f0cc44bf99ae978a6b75847a
|
||||
timeCreated: 1768127778
|
||||
@@ -0,0 +1,20 @@
|
||||
using Code.Example;
|
||||
using Reflex.Core;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Code.Infrastructure.App.SceneInstallers
|
||||
{
|
||||
public class MainMenuSceneInstaller : MonoBehaviour, IInstaller
|
||||
{
|
||||
public void InstallBindings(ContainerBuilder containerBuilder)
|
||||
{
|
||||
|
||||
containerBuilder.OnContainerBuilt += PostInstall;
|
||||
}
|
||||
|
||||
private void PostInstall(Container container)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 067978788f51445ca3af5381eafec386
|
||||
timeCreated: 1766393632
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 778cb4118a914d9c8b1cac8bef4295a5
|
||||
timeCreated: 1765572459
|
||||
@@ -0,0 +1,38 @@
|
||||
using Code.Infrastructure.Camera;
|
||||
using Code.Infrastructure.Generators;
|
||||
using Code.Infrastructure.SceneLoader;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
namespace Code.Infrastructure.App.States
|
||||
{
|
||||
[State(typeof(AppStates),typeof(AppStateMachineContext))]
|
||||
[StateRaisingEvent]
|
||||
public partial class BootstrapState : IOnGameplaySceneLoadedHandler
|
||||
{
|
||||
private EventBus.EventBus _eventBus;
|
||||
public BootstrapState(AppStateMachineContext context, EventBus.EventBus eventBus) : base(context,eventBus)
|
||||
{
|
||||
_eventBus = eventBus;
|
||||
}
|
||||
|
||||
public override AppStates myState => AppStates.Bootstrap;
|
||||
protected override void OnEnterState()
|
||||
{
|
||||
_eventBus.Subscribe(this);
|
||||
Context.Camera.SwitchState(CameraMode.FirstPerson).AllowStateTransition(CameraMode.None);
|
||||
Context.SceneLoader.LoadSceneAsync(SceneId.Gameplay, LoadSceneMode.Single).Forget();
|
||||
}
|
||||
|
||||
protected override void OnExitState()
|
||||
{
|
||||
_eventBus.Unsubscribe(this);
|
||||
}
|
||||
|
||||
public void OnGameplaySceneLoaded()
|
||||
{
|
||||
Debug.Log("Spermageddon");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 71df5370ea2e4819bfbdb9cbb8e6c0ab
|
||||
timeCreated: 1765572469
|
||||
@@ -0,0 +1,31 @@
|
||||
using Code.Infrastructure.Camera;
|
||||
using Code.Infrastructure.Generators;
|
||||
using Code.Infrastructure.SceneLoader;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Code.Infrastructure.App.States
|
||||
{
|
||||
[State(typeof(AppStates),typeof(AppStateMachineContext))]
|
||||
[StateRaisingEvent]
|
||||
public partial class GameplayState : IOnGameplaySceneLoadedHandler
|
||||
{
|
||||
public GameplayState(AppStateMachineContext context, EventBus.EventBus eventBus) : base(context, eventBus)
|
||||
{
|
||||
}
|
||||
|
||||
public override AppStates myState => AppStates.Gameplay;
|
||||
protected override void OnEnterState()
|
||||
{
|
||||
Context.Camera.SwitchState(CameraMode.FirstPerson).AllowStateTransition(CameraMode.None);
|
||||
}
|
||||
|
||||
protected override void OnExitState()
|
||||
{
|
||||
}
|
||||
|
||||
public void OnGameplaySceneLoaded()
|
||||
{
|
||||
Debug.Log("Spermageddon");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e543193800134f7b858502743ab3a43d
|
||||
timeCreated: 1766436900
|
||||
@@ -0,0 +1,22 @@
|
||||
using Code.Infrastructure.Generators;
|
||||
|
||||
namespace Code.Infrastructure.App.States
|
||||
{
|
||||
[State(typeof(AppStates),typeof(AppStateMachineContext))]
|
||||
[StateRaisingEvent]
|
||||
public partial class MainMenuState
|
||||
{
|
||||
public MainMenuState(AppStateMachineContext context, EventBus.EventBus eventBus) : base(context,eventBus)
|
||||
{
|
||||
}
|
||||
|
||||
public override AppStates myState => AppStates.MainMenu;
|
||||
protected override void OnEnterState()
|
||||
{
|
||||
}
|
||||
|
||||
protected override void OnExitState()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5a17221ff27a400e80c42a2ea60bb4ee
|
||||
timeCreated: 1766436796
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b7c28b6e1fe145b189d52cb829e06521
|
||||
timeCreated: 1766655751
|
||||
@@ -0,0 +1,61 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Code.Infrastructure.Configs;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using UnityEngine.AddressableAssets;
|
||||
using UnityEngine.ResourceManagement.AsyncOperations;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
namespace Code.Infrastructure.Camera
|
||||
{
|
||||
public class CameraFactory : IDisposable
|
||||
{
|
||||
private AsyncOperationHandle<GameCameraConfig> _configHandle;
|
||||
private GameCameraConfig _config;
|
||||
private AssetReference _gameCameraConfigReference;
|
||||
|
||||
private AsyncOperationHandle<IList<CameraSettingsConfig>> _settingsConfigsHandle;
|
||||
private Dictionary<CameraMode, CameraSettingsConfig> _settingsConfigs;
|
||||
private string _cameraConfigsLabel;
|
||||
|
||||
private EventBus.EventBus _eventBus;
|
||||
private UnityEngine.Camera _camera;
|
||||
private IDisposable _disposableImplementation;
|
||||
|
||||
public CameraFactory(IConfigLocator configLocator, EventBus.EventBus eventBus)
|
||||
{
|
||||
_gameCameraConfigReference = configLocator.TryGetConfigAssetReference<GameCameraConfig>();
|
||||
_cameraConfigsLabel = configLocator.TryGetManyConfigAssetReferences<CameraSettingsConfig>();
|
||||
|
||||
_eventBus = eventBus;
|
||||
}
|
||||
|
||||
public async UniTaskVoid CreateCameraStateMachine(CameraStateMachine stateMachine)
|
||||
{
|
||||
_settingsConfigsHandle = Addressables
|
||||
.LoadAssetsAsync<CameraSettingsConfig>(_cameraConfigsLabel, null, Addressables.MergeMode.Union);
|
||||
await _settingsConfigsHandle.ToUniTask();
|
||||
_settingsConfigs = _settingsConfigsHandle.Result.ToDictionary(x => x.cameraMode);
|
||||
|
||||
_configHandle = Addressables.LoadAssetAsync<GameCameraConfig>(_gameCameraConfigReference);
|
||||
await _configHandle.ToUniTask();
|
||||
_config = _configHandle.Result;
|
||||
|
||||
var cameraObject = await Addressables.InstantiateAsync(_config.Camera).ToUniTask();
|
||||
_camera = cameraObject.GetComponent<UnityEngine.Camera>();
|
||||
|
||||
cameraObject.GetComponent<CameraStateMachineRunner>().StateMachine = stateMachine;
|
||||
Object.DontDestroyOnLoad(cameraObject);
|
||||
|
||||
_eventBus.RaiseEvent<ICameraInitializedHandle>(x => x.CameraInitialized(new(_camera, _settingsConfigs)));
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Addressables.Release(_configHandle);
|
||||
Addressables.Release(_settingsConfigsHandle);
|
||||
Addressables.ReleaseInstance(_camera.gameObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4c05e01628b742be94dfd0bbbdfb87fa
|
||||
timeCreated: 1767302222
|
||||
@@ -0,0 +1,38 @@
|
||||
using Code.Infrastructure.Generators;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Code.Infrastructure.Camera
|
||||
{
|
||||
[Config("Configs/Camera/CameraSettings", true)]
|
||||
public class CameraSettings
|
||||
{
|
||||
// Расстояния от персонажа до камеры
|
||||
[ToConfig] public float defaultDistance = 6f; // Стандартное расстояние камеры от цели
|
||||
|
||||
[ToConfig] public float minDistance = 3f; // Минимальное расстояние при зуме
|
||||
|
||||
[ToConfig] public float maxDistance = 10f; // Максимальное расстояние при зуме
|
||||
|
||||
[ToConfig] public float distanceMovementSpeed = 5f; // Множитель скорости изменения дистанции при зуме
|
||||
|
||||
// Скорость поворота камеры
|
||||
[ToConfig] public float rotationSpeed = 0.3f;
|
||||
|
||||
[ToConfig] public float rotationSharpness = 100f; // Коэффициент плавности вращения камеры (чем выше - тем резче)
|
||||
|
||||
[ToConfig] public float followSharpness = 100f; // Коэффициент плавности следования за движущейся целью (чем выше - тем резче)
|
||||
|
||||
[ToConfig] public float minVerticalAngle = -70f; // Минимальный угол наклона камеры (вниз)
|
||||
|
||||
[ToConfig] public float maxVerticalAngle = 70f; // Максимальный угол наклона камеры (вверх)
|
||||
|
||||
[ToConfig] public float defaultVerticalAngle = 10f; // Стандартный угол наклона камеры
|
||||
|
||||
[ToConfig] public float fov = 60; // Комментарии оставляет только нейросеть и долбаёбы, никому и так не будет понятно, что ты высрал
|
||||
|
||||
[ToConfig] public CameraMode cameraMode;
|
||||
|
||||
// Позиция следования по умолчанию
|
||||
[ToConfig] public Vector3 defaultFollowPosition = Vector3.zero;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5442de773645443b99f8b0733199a854
|
||||
timeCreated: 1766657458
|
||||
@@ -0,0 +1,54 @@
|
||||
using System.Collections.Generic;
|
||||
using Code.Infrastructure.EventBus;
|
||||
using Code.Infrastructure.Generators;
|
||||
using Code.Infrastructure.Input;
|
||||
using Reflex.Attributes;
|
||||
using UnityEngine.AddressableAssets;
|
||||
|
||||
namespace Code.Infrastructure.Camera
|
||||
{
|
||||
public enum CameraMode
|
||||
{
|
||||
None,
|
||||
FirstPerson,
|
||||
Static,
|
||||
Cinematic
|
||||
}
|
||||
|
||||
[Config("Configs/Camera/CameraConfig")]
|
||||
public class GameCamera
|
||||
{
|
||||
[ToConfig] public AssetReference Camera;
|
||||
}
|
||||
|
||||
public interface ICameraInitializedHandle : IGlobalSubscriber
|
||||
{
|
||||
void CameraInitialized(CameraStateMachineContext.CameraLoadedData data);
|
||||
}
|
||||
|
||||
public class CameraStateMachineContext
|
||||
{
|
||||
public class CameraLoadedData
|
||||
{
|
||||
public UnityEngine.Camera Camera;
|
||||
public Dictionary<CameraMode, CameraSettingsConfig> SettingsConfigs;
|
||||
|
||||
public CameraLoadedData(UnityEngine.Camera camera, Dictionary<CameraMode, CameraSettingsConfig> settingsConfigs)
|
||||
{
|
||||
Camera = camera;
|
||||
SettingsConfigs = settingsConfigs;
|
||||
}
|
||||
}
|
||||
|
||||
public CameraLoadedData cameraLoadedData;
|
||||
|
||||
[Inject] public IInputService InputService;
|
||||
[Inject] public EventBus.EventBus EventBus;
|
||||
}
|
||||
|
||||
[Generators.StateMachine(typeof(CameraStateMachineContext), typeof(CameraMode))]
|
||||
public partial class CameraStateMachine
|
||||
{
|
||||
public UnityEngine.Camera Camera => StateMachineContext.cameraLoadedData.Camera;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b220b02510c34ea08257cc951d949fd7
|
||||
timeCreated: 1761671720
|
||||
@@ -0,0 +1,20 @@
|
||||
using Code.Infrastructure.Camera.CameraStates;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Code.Infrastructure.Camera
|
||||
{
|
||||
public class CameraStateMachineRunner : MonoBehaviour
|
||||
{
|
||||
public CameraStateMachine StateMachine;
|
||||
|
||||
private void Update()
|
||||
{
|
||||
((BaseCameraState)StateMachine.CurrentBaseState).Update();
|
||||
}
|
||||
|
||||
private void LateUpdate()
|
||||
{
|
||||
((BaseCameraState)StateMachine.CurrentBaseState).LateUpdate();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 293de8ebc2f54fa097ba2f1be8c8ed41
|
||||
timeCreated: 1767277431
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d7399e433dff42a185f62d79b546b059
|
||||
timeCreated: 1761671908
|
||||
@@ -0,0 +1,48 @@
|
||||
using Code.Infrastructure.StateMachine;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Code.Infrastructure.Camera.CameraStates
|
||||
{
|
||||
// [State(typeof(CameraMode),typeof(CameraStateMachineContext))]
|
||||
public abstract class BaseCameraState : BaseState<CameraMode, CameraStateMachineContext>
|
||||
{
|
||||
protected EventBus.EventBus _eventBus;
|
||||
|
||||
|
||||
// Трансформ объекта, за которым следует камера
|
||||
protected Transform FollowTransform;
|
||||
|
||||
// Позиция следования: текущая сглаженная позиция и горизонтальное направление камеры
|
||||
protected Vector3 CurrentFollowPosition;
|
||||
|
||||
// Целевой вертикальный угол камеры (наклон вверх/вниз)
|
||||
protected float TargetVerticalAngle;
|
||||
|
||||
// Текущая и целевая дистанция камеры от цели
|
||||
protected float CurrentDistance, TargetDistance;
|
||||
|
||||
// Исходные значения дистанции для восстановления
|
||||
protected float OriginalDefaultDistance, OriginalMinDistance, OriginalMaxDistance;
|
||||
|
||||
// Горизонтальное направление камеры (проекция forward на плоскость)
|
||||
protected Vector3 PlanarDirection { get; set; }
|
||||
protected BaseCameraState(CameraStateMachineContext context, EventBus.EventBus eventBus) : base(context, eventBus)
|
||||
{
|
||||
_eventBus = eventBus;
|
||||
}
|
||||
|
||||
// Основной метод обновления камеры, вызываемый извне каждый кадр
|
||||
protected void UpdateWithInput(float deltaTime, Vector3 rotationInput)
|
||||
{
|
||||
// Обработка ввода и позиционирования
|
||||
HandleRotationInput(deltaTime, rotationInput, out var targetRotation);
|
||||
HandlePosition(deltaTime , targetRotation);
|
||||
}
|
||||
|
||||
protected abstract void HandlePosition(float deltaTime, object o);
|
||||
|
||||
protected abstract void HandleRotationInput(float deltaTime, Vector3 rotationInput, out Quaternion q);
|
||||
public abstract void Update();
|
||||
public abstract void LateUpdate();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7901175f2c0646fda8741c4c269ce54b
|
||||
timeCreated: 1767127681
|
||||
@@ -0,0 +1,110 @@
|
||||
using Code.Example.Liminal.Player;
|
||||
using Code.Infrastructure.Generators;
|
||||
using Code.Infrastructure.Input;
|
||||
using UnityEngine;
|
||||
using UnityEngine.InputSystem;
|
||||
|
||||
namespace Code.Infrastructure.Camera.CameraStates
|
||||
{
|
||||
|
||||
[State(typeof(CameraMode),typeof(CameraStateMachineContext), true)]
|
||||
public partial class FirstPersonCameraState : BaseCameraState
|
||||
{
|
||||
private CameraSettingsConfig _settings;
|
||||
|
||||
public FirstPersonCameraState(CameraStateMachineContext context, EventBus.EventBus eventBus) : base(context, eventBus)
|
||||
{
|
||||
}
|
||||
|
||||
public override CameraMode myState => CameraMode.FirstPerson;
|
||||
protected override void OnEnterState()
|
||||
{
|
||||
_settings = Context.cameraLoadedData.SettingsConfigs[myState];
|
||||
|
||||
Context.InputService.BindActionPerformed((int)ActionMappings.Gameplay, (int) GameplayActions.Look, OnLookPerformed);
|
||||
Context.InputService.BindActionCancel((int)ActionMappings.Gameplay, (int) GameplayActions.Look, OnLookCanceled);
|
||||
}
|
||||
protected override void HandleRotationInput(float deltaTime, Vector3 rotationInput, out Quaternion targetRotation)
|
||||
{
|
||||
// Вращение вокруг вертикальной оси (горизонтальный поворот)
|
||||
var rotationFromInput = Quaternion.Euler(Vector3.up * (rotationInput.x * _settings.rotationSpeed));
|
||||
PlanarDirection = rotationFromInput * PlanarDirection;
|
||||
var planarRotation = Quaternion.LookRotation(PlanarDirection, FollowTransform.up);
|
||||
|
||||
// Вращение вокруг горизонтальной оси (вертикальный наклон)
|
||||
TargetVerticalAngle -= rotationInput.y * _settings.rotationSpeed;
|
||||
TargetVerticalAngle = Mathf.Clamp(TargetVerticalAngle, _settings.minVerticalAngle, _settings.maxVerticalAngle);
|
||||
var verticalRotation = Quaternion.Euler(TargetVerticalAngle, 0, 0);
|
||||
|
||||
// Интерполяция к целевому вращению для плавности
|
||||
targetRotation = Quaternion.Slerp(Context.cameraLoadedData.Camera.transform.rotation, planarRotation * verticalRotation, deltaTime * _settings.rotationSharpness);
|
||||
|
||||
// Применение финального вращения
|
||||
Context.cameraLoadedData.Camera.transform.rotation = targetRotation;
|
||||
}
|
||||
|
||||
protected override void OnExitState()
|
||||
{
|
||||
}
|
||||
|
||||
protected override void HandlePosition(float deltaTime, object targetRotation)
|
||||
{
|
||||
// Плавное следование за целью с использованием экспоненциального сглаживания
|
||||
// CurrentFollowPosition = Vector3.Lerp(CurrentFollowPosition, FollowTransform.position, 1f - Mathf.Exp(-_settings.followSharpness * deltaTime));
|
||||
|
||||
// В FirstPerson режиме камера находится прямо на позиции цели Да ну нахуй чё правда пиздец
|
||||
// var targetPosition = CurrentFollowPosition;
|
||||
|
||||
// Установка финальной позиции камеры Да ну нахуй чё правда пиздец
|
||||
Context.cameraLoadedData.Camera.transform.position = FollowTransform.position;
|
||||
}
|
||||
|
||||
private Vector2 _lookInput;
|
||||
|
||||
private void OnLookPerformed(InputAction.CallbackContext context)
|
||||
{
|
||||
_lookInput = context.ReadValue<Vector2>();
|
||||
}
|
||||
|
||||
private void OnLookCanceled(InputAction.CallbackContext context)
|
||||
{
|
||||
_lookInput = Vector2.zero;
|
||||
}
|
||||
|
||||
public override void Update()
|
||||
{
|
||||
}
|
||||
|
||||
public override void LateUpdate()
|
||||
{
|
||||
// Обновляем камеру только если есть цель для следования
|
||||
// if (FollowTransform)
|
||||
// {
|
||||
// UpdateWithInput(Time.deltaTime, _lookInput);
|
||||
// }
|
||||
if (_playerMovementController)
|
||||
{
|
||||
UpdateWithInput(Time.deltaTime, _lookInput);
|
||||
|
||||
_playerMovementController.SetCameraRotation(Context.cameraLoadedData.Camera.transform.rotation);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetFollowTransform(Transform t)
|
||||
{
|
||||
FollowTransform = t;
|
||||
CurrentFollowPosition = t.position;
|
||||
PlanarDirection = t.forward; // Начальное направление совпадает с направлением цели
|
||||
}
|
||||
|
||||
private PlayerMovementController _playerMovementController;
|
||||
public void SetPlayer(PlayerMovementController playerMovementController)
|
||||
{
|
||||
_playerMovementController = playerMovementController;
|
||||
|
||||
FollowTransform = _playerMovementController.PlayerHeadPoint;
|
||||
CurrentFollowPosition = _playerMovementController.PlayerHeadPoint.position;
|
||||
PlanarDirection = _playerMovementController.PlayerHeadPoint.forward; // Начальное направление совпадает с направлением цели
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 850f6325ab66480e9f7d1c03dbb37030
|
||||
timeCreated: 1767346203
|
||||
@@ -0,0 +1,40 @@
|
||||
using Code.Infrastructure.Generators;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Code.Infrastructure.Camera.CameraStates
|
||||
{
|
||||
[State(typeof(CameraMode),typeof(CameraStateMachineContext), true)]
|
||||
public partial class NoneCameraState : BaseCameraState
|
||||
{
|
||||
public NoneCameraState(CameraStateMachineContext context, EventBus.EventBus eventBus) : base(context, eventBus)
|
||||
{
|
||||
}
|
||||
|
||||
public override CameraMode myState => CameraMode.None;
|
||||
protected override void OnEnterState()
|
||||
{
|
||||
}
|
||||
|
||||
protected override void OnExitState()
|
||||
{
|
||||
}
|
||||
|
||||
protected override void HandlePosition(float deltaTime, object targetRotation)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
protected override void HandleRotationInput(float deltaTime, Vector3 rotationInput, out Quaternion q)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
public override void Update()
|
||||
{
|
||||
}
|
||||
|
||||
public override void LateUpdate()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cb14de48ff13488c8edb4431ac34e5be
|
||||
timeCreated: 1767301090
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ef0499dec5324e12b82f8688c6d3b3d8
|
||||
timeCreated: 1765711304
|
||||
@@ -0,0 +1,35 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Code.Infrastructure.SceneLoader;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using Reflex.Core;
|
||||
using UnityEngine;
|
||||
using UnityEngine.AddressableAssets;
|
||||
|
||||
namespace Code.Infrastructure.Configs
|
||||
{
|
||||
public partial class ConfigLocator : IConfigLocator
|
||||
{
|
||||
private Dictionary<Type, AssetReference> _singleConfigReferences = new();
|
||||
private Dictionary<Type, string> _multipleConfigReferences = new();
|
||||
|
||||
public AssetReference TryGetConfigAssetReference<T>() => _singleConfigReferences.GetValueOrDefault(typeof(T), null);
|
||||
public string TryGetManyConfigAssetReferences<T>() => _multipleConfigReferences.GetValueOrDefault(typeof(T), null);
|
||||
|
||||
partial void LoadConfigs();
|
||||
|
||||
public ConfigLocator()
|
||||
{
|
||||
LoadSystemConfigs();
|
||||
|
||||
LoadConfigs();
|
||||
}
|
||||
|
||||
private void LoadSystemConfigs()
|
||||
{
|
||||
SystemConfigsReferences systemConfigsReferences = Resources.Load<SystemConfigsReferences>("SystemConfigsReferences");
|
||||
|
||||
_singleConfigReferences.Add(typeof(ScenesAssetReferences), systemConfigsReferences.scenesAssetReferences);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 42496064fd5d42fea1c889f91e6a7e98
|
||||
timeCreated: 1765711330
|
||||
@@ -0,0 +1,11 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.AddressableAssets;
|
||||
|
||||
namespace Code.Infrastructure.Configs
|
||||
{
|
||||
[CreateAssetMenu(fileName = "SystemConfigsReferences", menuName = "Configs/SystemConfigsReferences")]
|
||||
public partial class SystemConfigsReferences : ScriptableObject
|
||||
{
|
||||
public AssetReference scenesAssetReferences;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 728b0ad306a64bd28d47fc4d052c5e81
|
||||
timeCreated: 1766325607
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7b34014c0c80c914baed6d14ef39dada
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,69 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Code.Infrastructure.EventBus
|
||||
{
|
||||
public class EventBus
|
||||
{
|
||||
private Dictionary<Type, SubscribersList<IGlobalSubscriber>> s_Subscribers
|
||||
= new();
|
||||
|
||||
public void Subscribe(IGlobalSubscriber subscriber)
|
||||
{
|
||||
List<Type> subscriberTypes = EventBusHelper.GetSubscriberTypes(subscriber);
|
||||
foreach (Type t in subscriberTypes)
|
||||
{
|
||||
if (!s_Subscribers.ContainsKey(t))
|
||||
{
|
||||
s_Subscribers[t] = new SubscribersList<IGlobalSubscriber>();
|
||||
}
|
||||
s_Subscribers[t].Add(subscriber);
|
||||
}
|
||||
}
|
||||
|
||||
public void Unsubscribe(IGlobalSubscriber subscriber)
|
||||
{
|
||||
List<Type> subscriberTypes = EventBusHelper.GetSubscriberTypes(subscriber);
|
||||
foreach (Type t in subscriberTypes)
|
||||
{
|
||||
if (s_Subscribers.ContainsKey(t))
|
||||
s_Subscribers[t].Remove(subscriber);
|
||||
}
|
||||
}
|
||||
|
||||
public void RaiseEvent<TSubscriber>(Action<TSubscriber> action)
|
||||
where TSubscriber : class, IGlobalSubscriber
|
||||
{
|
||||
if (!s_Subscribers.ContainsKey(typeof(TSubscriber))) return;
|
||||
|
||||
SubscribersList<IGlobalSubscriber> subscribers = s_Subscribers[typeof(TSubscriber)];
|
||||
|
||||
subscribers.Executing = true;
|
||||
|
||||
InvokeSubscribers(action, subscribers);
|
||||
|
||||
subscribers.Executing = false;
|
||||
subscribers.Cleanup();
|
||||
}
|
||||
|
||||
private void InvokeSubscribers<TSubscriber>(Action<TSubscriber> action, SubscribersList<IGlobalSubscriber> subscribers)
|
||||
where TSubscriber : class, IGlobalSubscriber
|
||||
{
|
||||
for ( int i = 0; i < subscribers.List.Count; i++)
|
||||
{
|
||||
Debug.Log("Invoking " + typeof(TSubscriber).Name);
|
||||
IGlobalSubscriber subscriber = subscribers.List[i];
|
||||
try
|
||||
{
|
||||
action.Invoke(subscriber as TSubscriber);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogError(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b0547f2543ccf5e47b9ec486f35aa2df
|
||||
@@ -0,0 +1,31 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Code.Infrastructure.EventBus
|
||||
{
|
||||
internal static class EventBusHelper
|
||||
{
|
||||
private static Dictionary<Type, List<Type>> s_CashedSubscriberTypes =
|
||||
new();
|
||||
|
||||
public static List<Type> GetSubscriberTypes(
|
||||
IGlobalSubscriber globalSubscriber)
|
||||
{
|
||||
Type type = globalSubscriber.GetType();
|
||||
if (s_CashedSubscriberTypes.ContainsKey(type))
|
||||
{
|
||||
return s_CashedSubscriberTypes[type];
|
||||
}
|
||||
|
||||
List<Type> subscriberTypes = type
|
||||
.GetInterfaces()
|
||||
.Where(t => t.GetInterfaces()
|
||||
.Contains(typeof(IGlobalSubscriber)))
|
||||
.ToList();
|
||||
|
||||
s_CashedSubscriberTypes[type] = subscriberTypes;
|
||||
return subscriberTypes;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ab2b1bcff76d5614dbda77a3c7b24158
|
||||
@@ -0,0 +1,5 @@
|
||||
namespace Code.Infrastructure.EventBus
|
||||
{
|
||||
public interface IGlobalSubscriber
|
||||
{ }
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fe414b0de24841347b03eec77d1855c0
|
||||
@@ -0,0 +1,46 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Code.Infrastructure.EventBus
|
||||
{
|
||||
internal class SubscribersList<TSubscriber> where TSubscriber : class
|
||||
{
|
||||
private bool m_NeedsCleanUp;
|
||||
|
||||
public bool Executing;
|
||||
|
||||
public readonly List<TSubscriber> List = new(); // TODO Weakptr
|
||||
|
||||
public void Add(TSubscriber subscriber)
|
||||
{
|
||||
List.Add(subscriber);
|
||||
}
|
||||
|
||||
public void Remove(TSubscriber subscriber)
|
||||
{
|
||||
if (Executing)
|
||||
{
|
||||
var i = List.IndexOf(subscriber);
|
||||
if (i >= 0)
|
||||
{
|
||||
m_NeedsCleanUp = true;
|
||||
List[i] = null;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
List.Remove(subscriber);
|
||||
}
|
||||
}
|
||||
|
||||
public void Cleanup()
|
||||
{
|
||||
if (!m_NeedsCleanUp)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
List.RemoveAll(s => s == null);
|
||||
m_NeedsCleanUp = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d364e9c8ac1c255428486d5892d23c1d
|
||||
File renamed without changes.
@@ -0,0 +1,49 @@
|
||||
using System;
|
||||
|
||||
namespace Code.Infrastructure.Generators
|
||||
{
|
||||
public class StateMachine : Attribute
|
||||
{
|
||||
public Type StateMachineContextType;
|
||||
public Type StateMachineEnumType;
|
||||
|
||||
public StateMachine(Type stateMachineContextType, Type stateMachineEnumType)
|
||||
{
|
||||
StateMachineContextType = stateMachineContextType;
|
||||
StateMachineEnumType = stateMachineEnumType;
|
||||
}
|
||||
}
|
||||
|
||||
public class State : Attribute
|
||||
{
|
||||
public Type StateEnum;
|
||||
public Type StateMachineContext;
|
||||
public bool SilentBitch; // Поэтому нейминг переменных очень важен
|
||||
|
||||
public State(Type stateEnum,Type stateMachineContext, bool silentBitch = false)
|
||||
{
|
||||
StateEnum = stateEnum;
|
||||
StateMachineContext = stateMachineContext;
|
||||
SilentBitch = silentBitch;
|
||||
}
|
||||
}
|
||||
public class StateRaisingEvent : Attribute
|
||||
{
|
||||
}
|
||||
public class Config : Attribute
|
||||
{
|
||||
public bool Multiple;
|
||||
public string MenuName;
|
||||
public Config(string menuName, bool multiple = false)
|
||||
{
|
||||
Multiple = multiple;
|
||||
MenuName = menuName;
|
||||
}
|
||||
}
|
||||
public class ToConfig : Attribute
|
||||
{
|
||||
}
|
||||
public class SceneIdEnum : Attribute
|
||||
{
|
||||
}
|
||||
}
|
||||
File renamed without changes.
@@ -0,0 +1,109 @@
|
||||
using System.Linq;
|
||||
using Unity.VisualScripting;
|
||||
using UnityCodeGen;
|
||||
using UnityEditor;
|
||||
|
||||
namespace Code.Infrastructure.Generators
|
||||
{
|
||||
[Generator]
|
||||
public class ConfigGenerator : ICodeGenerator
|
||||
{
|
||||
public void Execute(GeneratorContext context)
|
||||
{
|
||||
var configs = TypeCache.GetTypesWithAttribute<Config>();
|
||||
|
||||
var configsCode = "";
|
||||
var configAddCode = "";
|
||||
var configReferencesCode = "";
|
||||
var configReferencesUsingsCode = "";
|
||||
var configOfConfigsCode = "";
|
||||
|
||||
foreach (var cfg in configs)
|
||||
{
|
||||
var configFields = "";
|
||||
var configUsings = "";
|
||||
|
||||
var mem = cfg.GetFields();
|
||||
var members = mem.Where(m => m.HasAttribute<ToConfig>()).ToList();
|
||||
foreach (var m in members)
|
||||
{
|
||||
configUsings += $"using {m.FieldType.Namespace};\n";
|
||||
configFields += $"public {m.FieldType.FullName} {m.Name};\n";
|
||||
}
|
||||
|
||||
var attribute = cfg.GetAttribute<Config>();
|
||||
|
||||
configUsings += @"
|
||||
using UnityEngine;
|
||||
using UnityEngine.AddressableAssets;
|
||||
";
|
||||
var configCode = $@"
|
||||
#pragma warning disable CS0105
|
||||
{configUsings}
|
||||
namespace {cfg.Namespace}{{
|
||||
#pragma warning restore CS0105
|
||||
[CreateAssetMenu(fileName = ""{cfg.Name}Config"", menuName = ""{attribute.MenuName}"")]
|
||||
public class {cfg.Name}Config : ScriptableObject
|
||||
{{
|
||||
{configFields}
|
||||
}}
|
||||
}}
|
||||
";
|
||||
context.AddCode($"{cfg.Name}Config.Generated.cs", configCode);
|
||||
|
||||
configReferencesUsingsCode += $"using {cfg.Namespace};\n";
|
||||
|
||||
if (attribute.Multiple)
|
||||
{
|
||||
configReferencesCode += $"public string {cfg.Name};\n";
|
||||
configAddCode += $@"
|
||||
_multipleConfigReferences.Add(typeof({cfg.FullName}Config), systemConfigsReferences.{cfg.Name});
|
||||
";
|
||||
}
|
||||
else
|
||||
{
|
||||
configReferencesCode += $"public AssetReference {cfg.Name};\n";
|
||||
configAddCode += $@"
|
||||
_singleConfigReferences.Add(typeof({cfg.FullName}Config), systemConfigsReferences.{cfg.Name});
|
||||
";
|
||||
}
|
||||
}
|
||||
configsCode += $@"
|
||||
#pragma warning disable CS0105
|
||||
{configReferencesUsingsCode}
|
||||
using UnityEngine;
|
||||
#pragma warning restore CS0105
|
||||
|
||||
namespace Code.Infrastructure.Configs
|
||||
{{
|
||||
|
||||
public partial class ConfigLocator
|
||||
{{
|
||||
partial void LoadConfigs()
|
||||
{{
|
||||
SystemConfigsReferences systemConfigsReferences = Resources.Load<SystemConfigsReferences>(""SystemConfigsReferences"");
|
||||
{configAddCode}
|
||||
//_singleConfigReferences.Add(typeof(ScenesAssetReferences), systemConfigsReferences.scenesAssetReferences);
|
||||
}}
|
||||
}}
|
||||
}}
|
||||
";
|
||||
context.AddCode($"ConfigLocator.Generated.cs", configsCode);
|
||||
|
||||
configOfConfigsCode += $@"
|
||||
#pragma warning disable CS0105
|
||||
{configReferencesUsingsCode}
|
||||
using UnityEngine.AddressableAssets;
|
||||
#pragma warning restore CS0105
|
||||
|
||||
namespace Code.Infrastructure.Configs{{
|
||||
public partial class SystemConfigsReferences
|
||||
{{
|
||||
{configReferencesCode}
|
||||
}}
|
||||
}}
|
||||
";
|
||||
context.AddCode($"SystemConfigsReferences.Generated.cs", configOfConfigsCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 026403be8eae4546adcb407308031c1d
|
||||
timeCreated: 1765660396
|
||||
@@ -0,0 +1,148 @@
|
||||
using System.Linq;
|
||||
using Unity.VisualScripting;
|
||||
using UnityCodeGen;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Code.Infrastructure.Generators
|
||||
{
|
||||
[Generator]
|
||||
public class SceneLoaderGenerator : ICodeGenerator
|
||||
{
|
||||
public void Execute(GeneratorContext context)
|
||||
{
|
||||
var Enum = TypeCache.GetTypesWithAttribute<SceneIdEnum>();
|
||||
|
||||
var loaderCode = "";
|
||||
var dictionaryCode = "";
|
||||
var interfacesCode = "";
|
||||
var interfacesUsingsCode = $@"
|
||||
using Code.Infrastructure.EventBus;
|
||||
";
|
||||
|
||||
foreach (var en in Enum)
|
||||
{
|
||||
if (!en.IsEnum) return;
|
||||
|
||||
var members = en.GetFields();
|
||||
foreach (var member in members)
|
||||
{
|
||||
if(member.FieldType.FullName != en.FullName) continue;
|
||||
interfacesCode += $@"
|
||||
public interface IOn{member.Name}SceneLoadedHandler : IGlobalSubscriber
|
||||
{{
|
||||
void On{member.Name}SceneLoaded();
|
||||
}}
|
||||
";
|
||||
dictionaryCode += $@"
|
||||
|
||||
_scenesActions.Add(SceneId.{member.Name},() => _eventBus.RaiseEvent<IOn{member.Name}SceneLoadedHandler>(h=> h.On{member.Name}SceneLoaded()));
|
||||
";
|
||||
}
|
||||
}
|
||||
|
||||
loaderCode = $@"
|
||||
#pragma warning disable CS0105
|
||||
{interfacesUsingsCode}
|
||||
#pragma warning restore CS0105
|
||||
|
||||
namespace Code.Infrastructure.SceneLoader
|
||||
{{
|
||||
public partial class SceneLoader{{
|
||||
partial void SetupScenesInfo(){{
|
||||
{dictionaryCode}
|
||||
}}
|
||||
}}
|
||||
{interfacesCode}
|
||||
}}
|
||||
";
|
||||
context.AddCode($"SceneLoader.Generated.cs", loaderCode);
|
||||
// var configsCode = "";
|
||||
// var configCode = "";
|
||||
// var configUsings = "";
|
||||
// var configFields = "";
|
||||
// var configAddCode = "";
|
||||
// var configReferencesCode = "";
|
||||
// var configReferencesUsingsCode = "";
|
||||
// var configOfConfigsCode = "";
|
||||
//
|
||||
// foreach (var cfg in configs)
|
||||
// {
|
||||
// var mem = cfg.GetFields();
|
||||
// var members = mem.Where(m => m.HasAttribute<ToConfig>()).ToList();
|
||||
// foreach (var m in members)
|
||||
// {
|
||||
// configUsings += $"using {m.FieldType.Namespace};\n";
|
||||
// configFields += $"public {m.FieldType.FullName} {m.Name};\n";
|
||||
// }
|
||||
//
|
||||
// var attribute = cfg.GetAttribute<Config>();
|
||||
//
|
||||
// configUsings += @"
|
||||
// using UnityEngine;
|
||||
// using UnityEngine.AddressableAssets;
|
||||
// ";
|
||||
// configCode = $@"
|
||||
// {configUsings}
|
||||
// namespace {cfg.Namespace}{{
|
||||
// [CreateAssetMenu(fileName = ""{cfg.Name}Config"", menuName = ""{attribute.MenuName}"")]
|
||||
// public class {cfg.Name}Config : ScriptableObject
|
||||
// {{
|
||||
// {configFields}
|
||||
// }}
|
||||
// }}
|
||||
// ";
|
||||
// context.AddCode($"{cfg.Name}Config.Generated.cs", configCode);
|
||||
//
|
||||
// configReferencesUsingsCode += $"using {cfg.Namespace};\n";
|
||||
//
|
||||
// if (attribute.Multiple)
|
||||
// {
|
||||
// configReferencesCode += $"public String {cfg.Name};\n";
|
||||
// configAddCode += $@"
|
||||
// _multipleConfigReferences.Add(typeof({cfg.FullName}), systemConfigsReferences.{cfg.Name});
|
||||
// ";
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// configReferencesCode += $"public AssetReference {cfg.Name};\n";
|
||||
// configAddCode += $@"
|
||||
// _singleConfigReferences.Add(typeof({cfg.FullName}Config), systemConfigsReferences.{cfg.Name});
|
||||
// ";
|
||||
// }
|
||||
// }
|
||||
// configsCode += $@"
|
||||
// {configReferencesUsingsCode}
|
||||
// using UnityEngine;
|
||||
//
|
||||
// namespace Code.Infrastructure.Configs
|
||||
// {{
|
||||
//
|
||||
// public partial class ConfigLocator
|
||||
// {{
|
||||
// partial void LoadConfigs()
|
||||
// {{
|
||||
// SystemConfigsReferences systemConfigsReferences = Resources.Load<SystemConfigsReferences>(""SystemConfigsReferences"");
|
||||
// {configAddCode}
|
||||
// //_singleConfigReferences.Add(typeof(ScenesAssetReferences), systemConfigsReferences.scenesAssetReferences);
|
||||
// }}
|
||||
// }}
|
||||
// }}
|
||||
// ";
|
||||
// context.AddCode($"ConfigLocator.Generated.cs", configsCode);
|
||||
//
|
||||
// configOfConfigsCode += $@"
|
||||
// {configReferencesUsingsCode}
|
||||
// using UnityEngine.AddressableAssets;
|
||||
//
|
||||
// namespace Code.Infrastructure.Configs{{
|
||||
// public partial class SystemConfigsReferences
|
||||
// {{
|
||||
// {configReferencesCode}
|
||||
// }}
|
||||
// }}
|
||||
// ";
|
||||
// context.AddCode($"SystemConfigsReferences.Generated.cs", configOfConfigsCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 92ec56ffd46d4a569bb9a7d436790439
|
||||
timeCreated: 1766423754
|
||||
+65
-29
@@ -1,16 +1,21 @@
|
||||
using System.Linq;
|
||||
using Code.StateMachine;
|
||||
using Unity.VisualScripting;
|
||||
using UnityEditor;
|
||||
using UnityCodeGen;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
|
||||
namespace Code.Generators
|
||||
namespace Code.Infrastructure.Generators
|
||||
{
|
||||
[Generator]
|
||||
public class StateMachineGenerator : ICodeGenerator
|
||||
{
|
||||
public void Execute(GeneratorContext context)
|
||||
{
|
||||
GenerateStates(context);
|
||||
|
||||
GenerateStateMachine(context);
|
||||
}
|
||||
|
||||
private void GenerateStateMachine(GeneratorContext context)
|
||||
{
|
||||
var stateMachines = TypeCache.GetTypesWithAttribute<StateMachine>();
|
||||
|
||||
@@ -20,20 +25,19 @@ namespace Code.Generators
|
||||
|
||||
var states = TypeCache.GetTypesWithAttribute<State>()
|
||||
.Where(st =>
|
||||
st.GetAttribute<State>().StateMachineContextType.FullName ==
|
||||
st.GetAttribute<State>().StateMachineContext.FullName ==
|
||||
attribute.StateMachineContextType.FullName);
|
||||
|
||||
var statesCode = "";
|
||||
var statesNamespacesCode = "";
|
||||
|
||||
|
||||
var statesCode = "";
|
||||
var statesNamespacesCode = "";
|
||||
|
||||
foreach (var st in states)
|
||||
{
|
||||
var stateAttribute = st.GetAttribute<State>();
|
||||
{
|
||||
statesNamespacesCode += $@"
|
||||
using {st.Namespace};
|
||||
";
|
||||
statesCode += $@"
|
||||
var state{st.Name} = new {st.Name}(StateMachineContext);
|
||||
var state{st.Name} = new {st.Name}(StateMachineContext,eventBus);
|
||||
States.Add(state{st.Name}.myState, state{st.Name});
|
||||
";
|
||||
}
|
||||
@@ -41,18 +45,19 @@ States.Add(state{st.Name}.myState, state{st.Name});
|
||||
var stateMachineCode =
|
||||
$@"
|
||||
// <auto-generated/>
|
||||
using Code.StateMachine;
|
||||
#pragma warning disable CS0105
|
||||
using Code.Infrastructure.StateMachine;
|
||||
{statesNamespacesCode}
|
||||
#pragma warning restore CS0105
|
||||
namespace {sm.Namespace}
|
||||
{{
|
||||
|
||||
public partial class {sm.Name} : AbstractStateMachine<{attribute.StateMachineEnumType.FullName},{attribute.StateMachineContextType.FullName}>
|
||||
{{
|
||||
|
||||
public {sm.Name}()
|
||||
public {sm.Name}({attribute.StateMachineContextType.FullName} context, EventBus.EventBus eventBus) : base(context)
|
||||
{{
|
||||
{statesCode}
|
||||
CurrentBaseState = States[default({attribute.StateMachineEnumType.FullName})];
|
||||
}}
|
||||
|
||||
protected override bool CheckTransitionAllowed({attribute.StateMachineEnumType.FullName} nextState) => AllowedStates.HasFlag(nextState);
|
||||
@@ -74,22 +79,53 @@ public partial class {sm.Name} : AbstractStateMachine<{attribute.StateMachineEnu
|
||||
|
||||
";
|
||||
|
||||
// var publicFields = t.GetFields()
|
||||
// .Where(x => x.IsPublic && !x.IsStatic)
|
||||
// .Select(x => $"{x.Name}:{{{x.Name}}}");
|
||||
|
||||
// var toString = string.Join(", ", publicFields);
|
||||
// var code =
|
||||
// $@"// <auto-generated/>
|
||||
// partial class {t.Name}
|
||||
// {{
|
||||
// public override string ToString()
|
||||
// {{
|
||||
// return $""{toString}"";
|
||||
// }}
|
||||
// }}";
|
||||
context.AddCode($"{sm.FullName}.Generated.cs", stateMachineCode);
|
||||
}
|
||||
}
|
||||
|
||||
private void GenerateStates(GeneratorContext context)
|
||||
{
|
||||
var states = TypeCache.GetTypesWithAttribute<State>();
|
||||
|
||||
var statesCode = "";
|
||||
foreach (var st in states)
|
||||
{
|
||||
var attribute = st.GetAttribute<State>();
|
||||
|
||||
var fireStatesCode = "";
|
||||
if(st.HasAttribute<StateRaisingEvent>()) fireStatesCode = $@"
|
||||
protected override void _fireEnterState()
|
||||
{{
|
||||
EventBus.RaiseEvent<IEnterStateHandle<{st.FullName}>>(h => h.EnterState());
|
||||
}}
|
||||
|
||||
protected override void _fireExitState()
|
||||
{{
|
||||
EventBus.RaiseEvent<IExitStateHandle<{st.FullName}>>(h => h.ExitState());
|
||||
}}
|
||||
";
|
||||
var genetics = "";
|
||||
if(!attribute.SilentBitch) genetics = $@" : BaseState<{attribute.StateEnum.FullName}, {attribute.StateMachineContext.FullName}>";
|
||||
|
||||
statesCode = $@"
|
||||
|
||||
// retard-generated
|
||||
|
||||
using Code.Infrastructure.StateMachine;
|
||||
|
||||
namespace {st.Namespace}
|
||||
{{
|
||||
public partial class {st.Name} {genetics}
|
||||
{{
|
||||
{fireStatesCode}
|
||||
}}
|
||||
}}
|
||||
";
|
||||
|
||||
|
||||
context.AddCode($"{st.FullName}.Generated.cs", statesCode);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
File renamed without changes.
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 629db0b5c4ac4624b5bde7022e167b3b
|
||||
timeCreated: 1766612368
|
||||
@@ -0,0 +1,26 @@
|
||||
namespace Code.Infrastructure.Input
|
||||
{
|
||||
public enum ActionMappings
|
||||
{
|
||||
MainMenu,
|
||||
Gameplay,
|
||||
Debug
|
||||
}
|
||||
public enum GameplayActions
|
||||
{
|
||||
Move,
|
||||
Crouch,
|
||||
Look,
|
||||
Zoom
|
||||
}
|
||||
public enum DebugActions
|
||||
{
|
||||
Debug1,
|
||||
Debug2,
|
||||
Debug3,
|
||||
Debug4,
|
||||
Debug5,
|
||||
Debug6,
|
||||
Debug7
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dc62fec94fde411ab1420155a5087d64
|
||||
timeCreated: 1766613550
|
||||
@@ -0,0 +1,15 @@
|
||||
using System;
|
||||
using UnityEngine.InputSystem;
|
||||
|
||||
namespace Code.Infrastructure.Input
|
||||
{
|
||||
public interface IInputService
|
||||
{
|
||||
void EnableMap(ActionMappings actionMap);
|
||||
void DisableMap(ActionMappings actionMap);
|
||||
void BindActionPerformed(int mapId, int actionId, Action<InputAction.CallbackContext> action);
|
||||
void BindActionCancel(int mapId, int actionId, Action<InputAction.CallbackContext> action);
|
||||
void UnbindActionPerformed(int mapId, int actionId, Action<InputAction.CallbackContext> action);
|
||||
void UnbindActionCanceled(int mapId, int actionId, Action<InputAction.CallbackContext> action);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9443ed0c0d76423f8ecebbd9398bacf3
|
||||
timeCreated: 1766614201
|
||||
@@ -0,0 +1,62 @@
|
||||
using System;
|
||||
using Code.Infrastructure.Configs;
|
||||
using Code.Infrastructure.EventBus;
|
||||
using Code.Infrastructure.Generators;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using UnityEngine.AddressableAssets;
|
||||
using UnityEngine.InputSystem;
|
||||
using UnityEngine.ResourceManagement.AsyncOperations;
|
||||
|
||||
namespace Code.Infrastructure.Input
|
||||
{
|
||||
[Config("Configs/InputService")]
|
||||
public class InputService : IInputService
|
||||
{
|
||||
[ToConfig] public InputActionAsset inputActionAsset;
|
||||
private EventBus.EventBus _eventBus;
|
||||
|
||||
public InputService(IConfigLocator configLocator, EventBus.EventBus eventBus)
|
||||
{
|
||||
_eventBus = eventBus;
|
||||
LoadConfigs(configLocator.TryGetConfigAssetReference<InputServiceConfig>()).Forget();
|
||||
}
|
||||
|
||||
private AsyncOperationHandle<InputServiceConfig> _configHandle;
|
||||
|
||||
private async UniTaskVoid LoadConfigs(AssetReference configReference)
|
||||
{
|
||||
_configHandle = Addressables.LoadAssetAsync<InputServiceConfig>(configReference);
|
||||
|
||||
await _configHandle.ToUniTask();
|
||||
|
||||
inputActionAsset = _configHandle.Result.inputActionAsset;
|
||||
|
||||
inputActionAsset.actionMaps[(int)ActionMappings.Debug].Enable();
|
||||
inputActionAsset.actionMaps[(int)ActionMappings.Gameplay].Enable();
|
||||
|
||||
_eventBus.RaiseEvent<IInputServiceInitializedHandle>(h => h.InputServiceInitialized());
|
||||
}
|
||||
|
||||
public void EnableMap(ActionMappings actionMap) => inputActionAsset.actionMaps[(int)actionMap].Enable();
|
||||
public void DisableMap(ActionMappings actionMap) => inputActionAsset.actionMaps[(int)actionMap].Disable();
|
||||
|
||||
public void BindActionPerformed(int mapId, int actionId, Action<InputAction.CallbackContext> action) => inputActionAsset
|
||||
.actionMaps[mapId].actions[actionId].performed += action;
|
||||
|
||||
public void BindActionCancel(int mapId, int actionId, Action<InputAction.CallbackContext> action) => inputActionAsset
|
||||
.actionMaps[mapId].actions[actionId].canceled += action;
|
||||
|
||||
public void UnbindActionPerformed(int mapId, int actionId, Action<InputAction.CallbackContext> action) =>
|
||||
inputActionAsset
|
||||
.actionMaps[mapId].actions[actionId].performed -= action;
|
||||
|
||||
public void UnbindActionCanceled(int mapId, int actionId, Action<InputAction.CallbackContext> action) =>
|
||||
inputActionAsset
|
||||
.actionMaps[mapId].actions[actionId].canceled -= action;
|
||||
}
|
||||
|
||||
public interface IInputServiceInitializedHandle : IGlobalSubscriber
|
||||
{
|
||||
void InputServiceInitialized();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2755e684d68a4f79994f0f92e8327a73
|
||||
timeCreated: 1766612399
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d78dfc7c05e54743bfa99dfeaa7dc064
|
||||
timeCreated: 1766483099
|
||||
@@ -0,0 +1,29 @@
|
||||
using System;
|
||||
|
||||
namespace Code.Infrastructure.Loadings
|
||||
{
|
||||
public class Loading
|
||||
{
|
||||
private int _progress;
|
||||
private Action _completed;
|
||||
private Action<Loading> _loadProgress;
|
||||
|
||||
public Loading(int maxProgress, Action completed, Action<Loading> loadProgress = null)
|
||||
{
|
||||
_progress = maxProgress;
|
||||
MaxProgress = maxProgress;
|
||||
|
||||
_completed = completed;
|
||||
_loadProgress = loadProgress;
|
||||
}
|
||||
public int CurrentProgress => _progress;
|
||||
public int MaxProgress { get; }
|
||||
|
||||
public void DoProgress()
|
||||
{
|
||||
_progress--;
|
||||
_loadProgress?.Invoke(this);
|
||||
if(_progress <= 0) _completed();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a1707a55b78d4218b1557d42adb7d961
|
||||
timeCreated: 1766483205
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b7568293a2874477b2faeb918157ca94
|
||||
timeCreated: 1766325345
|
||||
@@ -0,0 +1,11 @@
|
||||
using Code.Infrastructure.Generators;
|
||||
|
||||
namespace Code.Infrastructure.SceneLoader
|
||||
{
|
||||
[SceneIdEnum]
|
||||
public enum SceneId
|
||||
{
|
||||
MainMenu,
|
||||
Gameplay
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: af1da0e870d542f2a864d7ddbbe9fb4c
|
||||
timeCreated: 1766396924
|
||||
@@ -0,0 +1,82 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Code.Infrastructure.Configs;
|
||||
using Code.Infrastructure.EventBus;
|
||||
using Code.Infrastructure.Generators;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
using UnityEngine.AddressableAssets;
|
||||
using UnityEngine.ResourceManagement.AsyncOperations;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
namespace Code.Infrastructure.SceneLoader
|
||||
{
|
||||
[Config("Configs/SceneConfig",true)]
|
||||
public class SceneInfo
|
||||
{
|
||||
[ToConfig] public AssetReference SceneAsset;
|
||||
[ToConfig] public SceneId SceneId;
|
||||
}
|
||||
public partial class SceneLoader : IDisposable
|
||||
{
|
||||
private Dictionary<SceneId, SceneInfo> _sceneInfos = new();
|
||||
private Dictionary<SceneId, Action> _scenesActions = new();
|
||||
|
||||
private EventBus.EventBus _eventBus;
|
||||
|
||||
partial void SetupScenesInfo();
|
||||
|
||||
private AsyncOperationHandle<IList<SceneInfoConfig>> _loadHandle;
|
||||
|
||||
public SceneLoader(EventBus.EventBus eventBus, IConfigLocator configLocator)
|
||||
{
|
||||
_eventBus = eventBus;
|
||||
LoadConfigs(configLocator.TryGetManyConfigAssetReferences<SceneInfoConfig>()).Forget();
|
||||
}
|
||||
|
||||
// TODO типилище
|
||||
public async UniTaskVoid LoadSceneAsync(SceneId id, LoadSceneMode loadMode)
|
||||
{
|
||||
await Addressables.LoadSceneAsync(_sceneInfos[id].SceneAsset, loadMode);
|
||||
|
||||
_scenesActions[id]();
|
||||
}
|
||||
|
||||
private AsyncOperationHandle<IList<SceneInfoConfig>> _configHandle;
|
||||
|
||||
private async UniTaskVoid LoadConfigs(string configReferences)
|
||||
{
|
||||
_configHandle = Addressables.LoadAssetsAsync<SceneInfoConfig>(configReferences, OnSceneConfigLoaded, Addressables.MergeMode.Union);
|
||||
|
||||
await _configHandle.ToUniTask();
|
||||
|
||||
SetupScenesInfo();
|
||||
_eventBus.RaiseEvent<ISceneConfigsLoadedHandle>(h => h.SceneConfigsLoaded());
|
||||
}
|
||||
|
||||
|
||||
private void OnSceneConfigLoaded(SceneInfoConfig sceneInfoConfig)
|
||||
{
|
||||
SceneInfo sceneInfo = new();
|
||||
sceneInfo.SceneId = sceneInfoConfig.SceneId;
|
||||
sceneInfo.SceneAsset = sceneInfoConfig.SceneAsset;
|
||||
|
||||
_sceneInfos.Add(sceneInfoConfig.SceneId, sceneInfo);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Addressables.Release(_configHandle);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public interface ISceneConfigsLoadedHandle : IGlobalSubscriber
|
||||
{
|
||||
void SceneConfigsLoaded();
|
||||
}
|
||||
public interface ILoadedSceneHandle : IGlobalSubscriber
|
||||
{
|
||||
void SceneLoaded(SceneId sceneId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 760817ac86164799ac58327509052257
|
||||
timeCreated: 1766325358
|
||||
@@ -0,0 +1,11 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.AddressableAssets;
|
||||
|
||||
namespace Code.Infrastructure.SceneLoader
|
||||
{
|
||||
[CreateAssetMenu(fileName = "ScenesAssetReferences", menuName = "Configs/ScenesAssetReferences")]
|
||||
public class ScenesAssetReferences : ScriptableObject
|
||||
{
|
||||
public AssetReference gameplaySceneReference;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9759979f397044a5bcb03ded0d1c9561
|
||||
timeCreated: 1766325404
|
||||
File renamed without changes.
+24
-32
@@ -1,38 +1,35 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using Code.Infrastructure.EventBus;
|
||||
|
||||
namespace Code.StateMachine
|
||||
namespace Code.Infrastructure.StateMachine
|
||||
{
|
||||
public abstract class AbstractStateMachine<TStateEnum, TStateMachineContext>
|
||||
where TStateMachineContext : new()
|
||||
{
|
||||
protected AbstractStateMachine(TStateMachineContext stateMachineContext )
|
||||
{
|
||||
StateMachineContext = stateMachineContext;
|
||||
}
|
||||
|
||||
public TStateEnum CurrentState { get; protected set; }
|
||||
public BaseState<TStateEnum, TStateMachineContext> CurrentBaseState { get; protected set; }
|
||||
public BaseState<TStateEnum, TStateMachineContext> CurrentBaseState { get; private set; }
|
||||
private BaseState<TStateEnum, TStateMachineContext> _previousBaseState;
|
||||
|
||||
protected Dictionary<TStateEnum, BaseState<TStateEnum, TStateMachineContext>> States = new();
|
||||
protected Dictionary<TStateEnum, Type> StatesTypes = new();
|
||||
public TStateEnum AllowedStates { get; set; }
|
||||
|
||||
public TStateMachineContext StateMachineContext { get; protected set; } = new();
|
||||
protected TStateMachineContext StateMachineContext { get; }
|
||||
|
||||
// protected virtual void Update()
|
||||
// {
|
||||
// CurrentBaseState.Tick();
|
||||
// }
|
||||
//
|
||||
// protected void LateUpdate()
|
||||
// {
|
||||
// CurrentBaseState.LateTick();
|
||||
// }
|
||||
|
||||
// Костыли 2 шт. для флагового енама в шаблонах
|
||||
protected abstract bool CheckTransitionAllowed(TStateEnum nextState);
|
||||
protected abstract void ResetAllowedTransitions();
|
||||
|
||||
// TODO Если в EnterState вызывается ExitState, то будет гарантированная поломка
|
||||
public virtual AbstractStateMachine<TStateEnum, TStateMachineContext> SwitchState(TStateEnum nextState)
|
||||
public AbstractStateMachine<TStateEnum, TStateMachineContext> SwitchState(TStateEnum nextState)
|
||||
{
|
||||
if (!CheckTransitionAllowed(nextState))
|
||||
if (!CheckTransitionAllowed(nextState) && CurrentBaseState != null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
@@ -43,28 +40,23 @@ namespace Code.StateMachine
|
||||
|
||||
CurrentBaseState = States[nextState];
|
||||
|
||||
if (_previousBaseState != null)
|
||||
{
|
||||
_previousBaseState.OnExited += CurrentBaseState.EnterState;
|
||||
_previousBaseState.OnExited += FinishBaseStateTransition;
|
||||
_previousBaseState.ExitState();
|
||||
}
|
||||
else
|
||||
{
|
||||
CurrentBaseState.EnterState();
|
||||
}
|
||||
_previousBaseState?.ExitState();
|
||||
|
||||
CurrentBaseState.EnterState();
|
||||
|
||||
CurrentState = nextState;
|
||||
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void FinishBaseStateTransition()
|
||||
{
|
||||
_previousBaseState.OnExited -= CurrentBaseState.EnterState;
|
||||
_previousBaseState.OnExited -= FinishBaseStateTransition;
|
||||
public interface IEnterStateHandle<TState> : IGlobalSubscriber
|
||||
{
|
||||
void EnterState();
|
||||
}
|
||||
|
||||
_previousBaseState = null;
|
||||
}
|
||||
public interface IExitStateHandle<TState> : IGlobalSubscriber
|
||||
{
|
||||
void ExitState();
|
||||
}
|
||||
}
|
||||
File renamed without changes.
@@ -0,0 +1,37 @@
|
||||
namespace Code.Infrastructure.StateMachine
|
||||
{
|
||||
public abstract class BaseState<TEnum, TStateMachineContext>
|
||||
{
|
||||
public abstract TEnum myState { get; }
|
||||
|
||||
protected BaseState(TStateMachineContext context, EventBus.EventBus eventBus)
|
||||
{
|
||||
Context = context;
|
||||
EventBus = eventBus;
|
||||
}
|
||||
|
||||
protected EventBus.EventBus EventBus;
|
||||
protected TStateMachineContext Context { get; }
|
||||
|
||||
protected virtual void _fireEnterState()
|
||||
{
|
||||
}
|
||||
|
||||
protected virtual void _fireExitState()
|
||||
{
|
||||
}
|
||||
|
||||
protected abstract void OnEnterState();
|
||||
protected abstract void OnExitState();
|
||||
public void EnterState()
|
||||
{
|
||||
OnEnterState();
|
||||
_fireEnterState();
|
||||
}
|
||||
public void ExitState()
|
||||
{
|
||||
OnExitState();
|
||||
_fireExitState();
|
||||
}
|
||||
}
|
||||
}
|
||||
File renamed without changes.
Loaded 100 of 734 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user