maint: renamed player folder to units to match namespaces. added unit class as well.
This commit is contained in:
55
Assets/Scripts/Units/CameraSettingData.cs
Normal file
55
Assets/Scripts/Units/CameraSettingData.cs
Normal file
@@ -0,0 +1,55 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Sirenix.OdinInspector;
|
||||
using UnityEngine;
|
||||
|
||||
[Serializable]
|
||||
public class CameraSettingData{
|
||||
[Title("Field of View"), HideLabel, InlineProperty] public SettingValue<float> mainFieldOfView = new SettingValue<float>(0f);
|
||||
|
||||
[Title("Orbit Position Damping"), HideLabel, InlineProperty] public SettingValue<Vector3> orbitPositionDamping = new SettingValue<Vector3>(Vector3.zero);
|
||||
[Title("Orbit Target Offset"), HideLabel, InlineProperty] public SettingValue<Vector3> orbitTargetOffset= new SettingValue<Vector3>(Vector3.zero);
|
||||
|
||||
[Title("X Axis Look Enabled"), HideLabel, InlineProperty] public SettingValue<bool> axisLookEnabledX = new SettingValue<bool>(true);
|
||||
[Title("Y Axis Look Enabled"), HideLabel, InlineProperty] public SettingValue<bool> axisLookEnabledY = new SettingValue<bool>(true);
|
||||
|
||||
[Title("X Axis Look Gain"), HideLabel, InlineProperty] public SettingValue<float> axisLookGainX = new SettingValue<float>(0f);
|
||||
[Title("Y Axis Look Gain"), HideLabel, InlineProperty] public SettingValue<float> axisLookGainY = new SettingValue<float>(0f);
|
||||
|
||||
[Title("Orbit Follow Top Height"), HideLabel, InlineProperty] public SettingValue<float> orbitFollowTopHeight = new SettingValue<float>(0f);
|
||||
[Title("Orbit Follow Top Radius"), HideLabel, InlineProperty] public SettingValue<float> orbitFollowTopRadius = new SettingValue<float>(0f);
|
||||
[Title("Orbit Follow Center Height"), HideLabel, InlineProperty] public SettingValue<float> orbitFollowCenterHeight = new SettingValue<float>(0f);
|
||||
[Title("Orbit Follow Center Radius"), HideLabel, InlineProperty] public SettingValue<float> orbitFollowCenterRadius = new SettingValue<float>(0f);
|
||||
[Title("Orbit Follow Bottom Height"), HideLabel, InlineProperty] public SettingValue<float> orbitFollowBottomHeight = new SettingValue<float>(0f);
|
||||
[Title("Orbit Follow Bottom Radius"), HideLabel, InlineProperty] public SettingValue<float> orbitFollowBottomRadius = new SettingValue<float>(0f);
|
||||
|
||||
public SettingValue<Vector2> rotationComposerScreenPos= new SettingValue<Vector2>(Vector2.zero);
|
||||
|
||||
public SettingValue<Vector3> cameraOffsetOffset= new SettingValue<Vector3>(Vector3.zero);
|
||||
|
||||
public List<IResettableSettingValue> GetAllSettings(){
|
||||
var outputList = new List<IResettableSettingValue>();
|
||||
|
||||
IResettableSettingValue[] settings = {
|
||||
mainFieldOfView,
|
||||
orbitPositionDamping,
|
||||
orbitTargetOffset,
|
||||
axisLookEnabledX,
|
||||
axisLookEnabledY,
|
||||
axisLookGainX,
|
||||
axisLookGainY,
|
||||
orbitFollowTopHeight,
|
||||
orbitFollowTopRadius,
|
||||
orbitFollowCenterHeight,
|
||||
orbitFollowCenterRadius,
|
||||
orbitFollowBottomHeight,
|
||||
orbitFollowBottomRadius,
|
||||
rotationComposerScreenPos,
|
||||
cameraOffsetOffset,
|
||||
};
|
||||
|
||||
outputList.AddRange(settings);
|
||||
|
||||
return outputList;
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Units/CameraSettingData.cs.meta
Normal file
3
Assets/Scripts/Units/CameraSettingData.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 14393bffe6324344b5f972412e37a339
|
||||
timeCreated: 1758568723
|
||||
114
Assets/Scripts/Units/CameraSettingsProcessor.cs
Normal file
114
Assets/Scripts/Units/CameraSettingsProcessor.cs
Normal file
@@ -0,0 +1,114 @@
|
||||
using System;
|
||||
using Reset.Core;
|
||||
using Sirenix.OdinInspector;
|
||||
using Unity.Cinemachine;
|
||||
using UnityEngine;
|
||||
|
||||
public class CameraSettingsProcessor : MonoBehaviour{
|
||||
public static CameraSettingsProcessor Instance{ get; private set; }
|
||||
|
||||
[ShowInInspector, FoldoutGroup("Camera Data", expanded: true), InlineProperty, HideLabel]
|
||||
public CameraSettingData data;
|
||||
|
||||
public static GameObject mainCamera;
|
||||
|
||||
private CinemachineCamera main;
|
||||
private CinemachineOrbitalFollow orbit;
|
||||
private CinemachineRotationComposer rotComp;
|
||||
private CinemachineCameraOffset offset;
|
||||
private CinemachineInputAxisController axisCont;
|
||||
|
||||
public void Awake(){
|
||||
// Singleton management
|
||||
if (Instance != null && Instance != this) {
|
||||
Destroy(this);
|
||||
} else {
|
||||
Instance = this;
|
||||
}
|
||||
|
||||
// Set references for camera object and cinemachine components
|
||||
mainCamera = gameObject;
|
||||
main = mainCamera.GetComponent<CinemachineCamera>();
|
||||
orbit = mainCamera.GetComponent<CinemachineOrbitalFollow>();
|
||||
rotComp = mainCamera.GetComponent<CinemachineRotationComposer>();
|
||||
offset = mainCamera.GetComponent<CinemachineCameraOffset>();
|
||||
axisCont = mainCamera.GetComponent<CinemachineInputAxisController>();
|
||||
|
||||
// Quick check for a camera settings
|
||||
if (data == null) {
|
||||
Debug.LogWarning("No Camera Settings Data was found on processing. One will be created. Is this intentional? This will have strong effects on camera movement");
|
||||
data = new CameraSettingData();
|
||||
}
|
||||
|
||||
// Initialize camera settings values from current values
|
||||
InitializeAllSettings();
|
||||
}
|
||||
|
||||
void Update(){
|
||||
SmoothCameraSettings();
|
||||
ApplyCameraSettings();
|
||||
}
|
||||
|
||||
void SmoothCameraSettings(){
|
||||
var settings = data.GetAllSettings();
|
||||
|
||||
for (int i = 0; i < settings.Count; i++) {
|
||||
settings[i].SmoothAndEase();
|
||||
}
|
||||
}
|
||||
|
||||
// Responsible for actively applying the settings to the Cinemachine components
|
||||
void ApplyCameraSettings(){
|
||||
main.Lens.FieldOfView = data.mainFieldOfView.Value;
|
||||
|
||||
axisCont.Controllers[0].Enabled = data.axisLookEnabledX.Value;
|
||||
axisCont.Controllers[1].Enabled = data.axisLookEnabledY.Value;
|
||||
|
||||
axisCont.Controllers[0].Input.Gain = data.axisLookGainX.Value;
|
||||
axisCont.Controllers[1].Input.Gain = data.axisLookGainY.Value;
|
||||
|
||||
orbit.TrackerSettings.PositionDamping = data.orbitPositionDamping.Value;
|
||||
orbit.TargetOffset = data.orbitTargetOffset.Value;
|
||||
|
||||
orbit.Orbits.Top.Height = data.orbitFollowTopHeight.Value;
|
||||
orbit.Orbits.Top.Radius = data.orbitFollowTopRadius.Value;
|
||||
orbit.Orbits.Center.Height = data.orbitFollowCenterHeight.Value;
|
||||
orbit.Orbits.Center.Radius = data.orbitFollowCenterRadius.Value;
|
||||
orbit.Orbits.Bottom.Height = data.orbitFollowBottomHeight.Value;
|
||||
orbit.Orbits.Bottom.Radius = data.orbitFollowBottomRadius.Value;
|
||||
|
||||
rotComp.Composition.ScreenPosition = data.rotationComposerScreenPos.Value;
|
||||
|
||||
offset.Offset = data.cameraOffsetOffset.Value;
|
||||
}
|
||||
|
||||
[Button]
|
||||
void InitializeAllSettings(){
|
||||
data.mainFieldOfView.targetValue = main.Lens.FieldOfView;
|
||||
|
||||
data.orbitPositionDamping.targetValue = orbit.TrackerSettings.PositionDamping;
|
||||
data.orbitTargetOffset.targetValue = orbit.TargetOffset;
|
||||
|
||||
data.axisLookEnabledX.targetValue = axisCont.Controllers[0].Enabled;
|
||||
data.axisLookEnabledY.targetValue = axisCont.Controllers[1].Enabled;
|
||||
|
||||
data.axisLookGainX.targetValue = axisCont.Controllers[0].Input.Gain;
|
||||
data.axisLookGainY.targetValue = axisCont.Controllers[1].Input.Gain;
|
||||
|
||||
data.orbitFollowTopHeight.targetValue = orbit.Orbits.Top.Height;
|
||||
data.orbitFollowTopRadius.targetValue = orbit.Orbits.Top.Radius;
|
||||
data.orbitFollowCenterHeight.targetValue = orbit.Orbits.Center.Height;
|
||||
data.orbitFollowCenterRadius.targetValue = orbit.Orbits.Center.Radius;
|
||||
data.orbitFollowBottomHeight.targetValue = orbit.Orbits.Bottom.Height;
|
||||
data.orbitFollowBottomRadius.targetValue = orbit.Orbits.Bottom.Radius;
|
||||
|
||||
data.rotationComposerScreenPos.targetValue = rotComp.Composition.ScreenPosition;
|
||||
data.cameraOffsetOffset.targetValue = offset.Offset;
|
||||
|
||||
var allSettings = data.GetAllSettings();
|
||||
for (int i = 0; i < allSettings.Count; i++) {
|
||||
allSettings[i].Initialize();
|
||||
allSettings[i].Verify();
|
||||
}
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/Units/CameraSettingsProcessor.cs.meta
Normal file
2
Assets/Scripts/Units/CameraSettingsProcessor.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c032a18b0b0c1da4092bfc365c6e4aad
|
||||
8
Assets/Scripts/Units/Combat.meta
Normal file
8
Assets/Scripts/Units/Combat.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3f97262ab9d9b0541b5e20e7e7673a7c
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
9
Assets/Scripts/Units/Combat/IDamageable.cs
Normal file
9
Assets/Scripts/Units/Combat/IDamageable.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Reset.Core{
|
||||
public interface IDamageable{
|
||||
public void TakeDamage(DamageSource source);
|
||||
public void TakeDamage(DamageSource[] sources);
|
||||
}
|
||||
|
||||
}
|
||||
2
Assets/Scripts/Units/Combat/IDamageable.cs.meta
Normal file
2
Assets/Scripts/Units/Combat/IDamageable.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f7a90e7b5a2e47747a524df1a8b3bc78
|
||||
72
Assets/Scripts/Units/Combat/UnitCombat.cs
Normal file
72
Assets/Scripts/Units/Combat/UnitCombat.cs
Normal file
@@ -0,0 +1,72 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Reset.Core.Tools;
|
||||
using Reset.Units;
|
||||
using UnityEngine;
|
||||
using Random = UnityEngine.Random;
|
||||
|
||||
public class UnitCombat : MonoBehaviour{
|
||||
public List<Collider> draggedUnits = new List<Collider>();
|
||||
|
||||
private UnitMovementHandler movement;
|
||||
|
||||
private Vector3 lastPosition;
|
||||
private Vector3 positionDelta;
|
||||
|
||||
private float lastSpeed;
|
||||
private float speedDelta;
|
||||
private float sinAmplitude;
|
||||
private float sinOffset;
|
||||
|
||||
void Awake(){
|
||||
movement = GetComponent<UnitMovementHandler>();
|
||||
}
|
||||
|
||||
void Start(){
|
||||
lastPosition = transform.position;
|
||||
sinOffset = Random.value;
|
||||
sinAmplitude = 1 + Random.value / 4f;
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void Update(){
|
||||
DragAttackedUnits();
|
||||
}
|
||||
|
||||
void DragAttackedUnits(){
|
||||
// Get the original difference in position for speed and direction
|
||||
positionDelta = Vector3.Lerp(positionDelta, lastPosition.DirectionTo(transform.position), 5f * Time.deltaTime);
|
||||
speedDelta = Vector3.Distance(lastPosition, transform.position) / Time.deltaTime;
|
||||
|
||||
// Add some randomness to the movements based on small offsets
|
||||
float sinVal = Mathf.Sin(2f + sinOffset) * sinAmplitude;
|
||||
speedDelta += sinVal;
|
||||
|
||||
// Set a floor to prevent them from not moving enough
|
||||
speedDelta = Mathf.Max(3f, speedDelta);
|
||||
|
||||
// Multiply the speed to be lower when further, and faster when close
|
||||
float speedDiff = Mathf.Lerp(.2f, 1.4f, speedDelta);
|
||||
speedDelta *= speedDiff;
|
||||
|
||||
// Debug
|
||||
DebugOverlayDrawer.ChangeValue($"Combat - {name}", "Position Delta", positionDelta);
|
||||
DebugOverlayDrawer.ChangeValue($"Combat - {name}", "Speed Delta", speedDelta);
|
||||
|
||||
// Update last known position
|
||||
lastPosition = transform.position;
|
||||
|
||||
// Apply the speed, direction, and rotation to each unit
|
||||
foreach (Collider draggedUnit in draggedUnits) {
|
||||
UnitMovementHandler draggedUnitMovement = draggedUnit.GetComponent<UnitMovementHandler>();
|
||||
if (!draggedUnitMovement) {
|
||||
Debug.LogError($"No available UnitMovement on {draggedUnit.name}. Aborting drag on this unit.");
|
||||
continue;
|
||||
}
|
||||
|
||||
draggedUnitMovement.SetNewRotation(-transform.position.DirectionTo(draggedUnit.transform.position), 1f, true);
|
||||
draggedUnitMovement.SetNewDirection((positionDelta).ToVector2(), 1f, true);
|
||||
draggedUnitMovement.SetNewSpeed(speedDelta, 1f, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/Units/Combat/UnitCombat.cs.meta
Normal file
2
Assets/Scripts/Units/Combat/UnitCombat.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7719da98d07bb4848a78904f6da4c355
|
||||
80
Assets/Scripts/Units/CustomInputHandler.cs
Normal file
80
Assets/Scripts/Units/CustomInputHandler.cs
Normal file
@@ -0,0 +1,80 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.InputSystem;
|
||||
using Unity.Cinemachine;
|
||||
|
||||
// This class receives input from a PlayerInput component and disptaches it
|
||||
// to the appropriate Cinemachine InputAxis. The playerInput component should
|
||||
// be on the same GameObject, or specified in the PlayerInput field.
|
||||
class CustomInputHandler : InputAxisControllerBase<CustomInputHandler.Reader>
|
||||
{
|
||||
[Header("Input Source Override")]
|
||||
public PlayerInput PlayerInput;
|
||||
|
||||
void Awake()
|
||||
{
|
||||
// // When the PlayerInput receives an input, send it to all the controllers
|
||||
// if (PlayerInput == null)
|
||||
// TryGetComponent(out PlayerInput);
|
||||
// if (PlayerInput == null)
|
||||
// Debug.LogError("Cannot find PlayerInput component");
|
||||
// else
|
||||
// {
|
||||
// PlayerInput.notificationBehavior = PlayerNotifications.InvokeCSharpEvents;
|
||||
// PlayerInput.onActionTriggered += (value) =>
|
||||
// {
|
||||
// for (var i = 0; i < Controllers.Count; i++)
|
||||
// Controllers[i].Input.ProcessInput(value.action);
|
||||
// };
|
||||
// }
|
||||
}
|
||||
|
||||
// We process user input on the Update clock
|
||||
void Update()
|
||||
{
|
||||
if (Application.isPlaying){
|
||||
UpdateControllers();
|
||||
Controllers[0].Input.ProcessInput(PlayerInput);
|
||||
Controllers[1].Input.ProcessInput(PlayerInput);
|
||||
}
|
||||
}
|
||||
|
||||
public void AddEvents(){
|
||||
// // PlayerInput.notificationBehavior = PlayerNotifications.InvokeCSharpEvents;
|
||||
// += (value) =>
|
||||
// {
|
||||
// for (var i = 0; i < Controllers.Count; i++)
|
||||
// Controllers[i].Input.ProcessInput(value.action);
|
||||
// };
|
||||
}
|
||||
|
||||
// Controllers will be instances of this class.
|
||||
[Serializable]
|
||||
public class Reader : IInputAxisReader
|
||||
{
|
||||
public InputActionReference Input;
|
||||
Vector2 m_Value; // the cached value of the input
|
||||
|
||||
public void ProcessInput(PlayerInput input){
|
||||
|
||||
// // If it's my action then cache the new value
|
||||
// if (Input != null && Input.action.id == action.id)
|
||||
// {
|
||||
// if (action.expectedControlType == "Vector2")
|
||||
// m_Value = action.ReadValue<Vector2>();
|
||||
// else
|
||||
// m_Value.x = m_Value.y = action.ReadValue<float>();
|
||||
// }
|
||||
|
||||
m_Value = input.actions["Look"].ReadValue<Vector2>();
|
||||
m_Value.x *= 200f;
|
||||
m_Value.y *= -100f;
|
||||
}
|
||||
|
||||
// IInputAxisReader interface: Called by the framework to read the input value
|
||||
public float GetValue(UnityEngine.Object context, IInputAxisOwner.AxisDescriptor.Hints hint)
|
||||
{
|
||||
return (hint == IInputAxisOwner.AxisDescriptor.Hints.Y ? m_Value.y : m_Value.x);
|
||||
}
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/Units/CustomInputHandler.cs.meta
Normal file
2
Assets/Scripts/Units/CustomInputHandler.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 058c862723373ca43913637463aff84a
|
||||
10
Assets/Scripts/Units/IKillable.cs
Normal file
10
Assets/Scripts/Units/IKillable.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
using Reset.Core;
|
||||
|
||||
namespace Reset.Units{
|
||||
public interface IKillable : IDamageable{
|
||||
public void Kill();
|
||||
|
||||
public float maxHealth{ get; set; }
|
||||
public float currentHealth{ get; set; }
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Units/IKillable.cs.meta
Normal file
3
Assets/Scripts/Units/IKillable.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a819219f1a77429aacb1aace2e346eab
|
||||
timeCreated: 1759535007
|
||||
49
Assets/Scripts/Units/InteractionHandler.cs
Normal file
49
Assets/Scripts/Units/InteractionHandler.cs
Normal file
@@ -0,0 +1,49 @@
|
||||
using Reset.Items;
|
||||
using UnityEngine;
|
||||
using UnityEngine.InputSystem;
|
||||
|
||||
namespace Reset.Units{
|
||||
public class InteractionHandler : MonoBehaviour{
|
||||
private PlayerEnvironmentManager envManager;
|
||||
private Inventory inventory;
|
||||
private EnvironmentObserver observer;
|
||||
|
||||
void Awake(){
|
||||
envManager = GetComponent<PlayerEnvironmentManager>();
|
||||
inventory = GetComponent<Inventory>();
|
||||
|
||||
observer = envManager.FindObserverFromString("itemdrop");
|
||||
|
||||
observer.active = true;
|
||||
}
|
||||
|
||||
public void InteractWith(GameObject target){
|
||||
IInteractable interactable = target.GetComponent<IInteractable>();
|
||||
|
||||
if (interactable == null) {
|
||||
Debug.LogError("This item cannot be interacted with, it has no Interactable interface");
|
||||
return;
|
||||
}
|
||||
|
||||
if (target.GetComponent<ItemDrop>()) {
|
||||
inventory.AddToInventory(target.GetComponent<ItemDrop>().item);
|
||||
}
|
||||
|
||||
interactable.Interact();
|
||||
|
||||
// Don't do any actions that use the same button (hard set to Jump for now)
|
||||
Debug.Log($"Just collected the item, consuming the input @ {Time.time}.");
|
||||
GetComponent<PlayerControls>().SendInputBlock("Jump");
|
||||
}
|
||||
|
||||
void OnInteract(){
|
||||
CheckForInteraction();
|
||||
}
|
||||
|
||||
private void CheckForInteraction(){
|
||||
if (observer.active && observer.Evaluate(gameObject)) {
|
||||
InteractWith(observer.hit.transform.gameObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/Units/InteractionHandler.cs.meta
Normal file
11
Assets/Scripts/Units/InteractionHandler.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 96023d711211b9843b01db23192fa84c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: -101
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
47
Assets/Scripts/Units/Inventory.cs
Normal file
47
Assets/Scripts/Units/Inventory.cs
Normal file
@@ -0,0 +1,47 @@
|
||||
using System.Collections.Generic;
|
||||
using NodeCanvas.Tasks.Actions;
|
||||
using Reset.Items;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Reset.Units{
|
||||
public class Inventory : MonoBehaviour{
|
||||
public Weapon rangedWeapon;
|
||||
public Weapon meleeWeapon;
|
||||
|
||||
public Ability spellAbility1;
|
||||
public Ability spellAbility2;
|
||||
|
||||
public Ability toolAbility1;
|
||||
public Ability toolAbility2;
|
||||
|
||||
public List<Item> storedItems = new List<Item>(15);
|
||||
|
||||
void Start(){
|
||||
|
||||
}
|
||||
|
||||
public void AddToInventory(Item newItem){
|
||||
storedItems.Add(newItem);
|
||||
}
|
||||
|
||||
public void Equip(Item item){
|
||||
if (item is not IEquipable) {
|
||||
Debug.LogError("This item is not equippable.", item);
|
||||
return;
|
||||
}
|
||||
|
||||
if (item is Weapon thisWeapon) {
|
||||
if (meleeWeapon != null) {
|
||||
storedItems.Add(meleeWeapon);
|
||||
}
|
||||
|
||||
meleeWeapon = thisWeapon;
|
||||
}
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void Update(){
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/Units/Inventory.cs.meta
Normal file
2
Assets/Scripts/Units/Inventory.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d57ab8ec1cbbdcf46813f268625d3494
|
||||
91
Assets/Scripts/Units/Player.cs
Normal file
91
Assets/Scripts/Units/Player.cs
Normal file
@@ -0,0 +1,91 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using Drawing;
|
||||
using Reset;
|
||||
using Reset.Core;
|
||||
using Reset.Core.Tools;
|
||||
using Reset.Units;
|
||||
using UnityEngine;
|
||||
using Sirenix.OdinInspector;
|
||||
using Sirenix.Serialization;
|
||||
using Unity.Netcode;
|
||||
|
||||
public class Player : Unit, IKillable{
|
||||
[HideInInspector] public PlayerControls controls;
|
||||
|
||||
float IKillable.maxHealth{ get; set; }
|
||||
float IKillable.currentHealth{ get; set; }
|
||||
|
||||
void Awake(){
|
||||
GameManager.Player = gameObject;
|
||||
controls = GetComponent<PlayerControls>();
|
||||
}
|
||||
|
||||
void Start(){
|
||||
if (((IKillable)this).maxHealth == 0f) {
|
||||
Debug.LogError($"Max health is not set for type of <b>{name}</b>. Setting to 100.");
|
||||
((IKillable)this).currentHealth = 10000f;
|
||||
} else {
|
||||
((IKillable)this).currentHealth = ((IKillable)this).maxHealth;
|
||||
}
|
||||
|
||||
|
||||
if (!NetworkManager.Singleton.IsConnectedClient && !NetworkManager.Singleton.IsHost) {
|
||||
Attach();
|
||||
} else {
|
||||
StartCoroutine(WaitForOnline());
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerator WaitForOnline(){
|
||||
while (!NetworkManager.Singleton.didAwake) {
|
||||
Debug.Log("waiting");
|
||||
yield return null;
|
||||
}
|
||||
|
||||
// Debug.Log($"{IsHost}, {IsClient}, {IsLocalPlayer}");
|
||||
if (IsLocalPlayer){
|
||||
GameManager.Player = gameObject;
|
||||
Attach();
|
||||
}
|
||||
}
|
||||
|
||||
public void Attach(){
|
||||
if (GameManager.Player == gameObject){
|
||||
GameManager.RequestNewController();
|
||||
GetComponent<LockOnManager>().AttachCamera(gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnNetworkPostSpawn(){
|
||||
// GetComponent<LockOnManager>().AttachCamera(gameObject);
|
||||
}
|
||||
|
||||
|
||||
// Update is called once per frame
|
||||
void Update(){
|
||||
using (Draw.WithColor(Color.blue)) {
|
||||
Draw.ingame.Label2D(transform.position + Vector3.up * 2.2f, ((IKillable)this).currentHealth.ToString(),
|
||||
Color.blue);
|
||||
}
|
||||
}
|
||||
|
||||
public void TakeDamage(DamageSource[] sources){
|
||||
foreach (DamageSource source in sources) {
|
||||
TakeDamage(source);
|
||||
}
|
||||
}
|
||||
|
||||
public void TakeDamage(DamageSource source){
|
||||
((IKillable)this).currentHealth -= source.damageDealt;
|
||||
|
||||
if (((IKillable)this).currentHealth <= 0) {
|
||||
Kill();
|
||||
}
|
||||
}
|
||||
|
||||
public void Kill(){
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
}
|
||||
2
Assets/Scripts/Units/Player.cs.meta
Normal file
2
Assets/Scripts/Units/Player.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0c0da0317d344ea49b810f0010efefa8
|
||||
53
Assets/Scripts/Units/PlayerCamera.cs
Normal file
53
Assets/Scripts/Units/PlayerCamera.cs
Normal file
@@ -0,0 +1,53 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
public interface ILockOnTarget {
|
||||
public float lockonTargetRadius { set; }
|
||||
|
||||
Transform transform {get;}
|
||||
GameObject gameObject{ get; }
|
||||
|
||||
abstract void OnTargetDelete();
|
||||
|
||||
void Help(){
|
||||
SafelyDeleteTarget();
|
||||
}
|
||||
|
||||
public Vector3 GetReticlePosition(){
|
||||
float upValue = 0f;
|
||||
|
||||
if (gameObject.GetComponent<Renderer>()){
|
||||
Bounds objectBounds = gameObject.GetComponent<Renderer>().bounds;
|
||||
upValue = objectBounds.size.y;
|
||||
}
|
||||
|
||||
Vector3 reticlePosition = new Vector3(transform.position.x, transform.position.y + upValue, transform.position.z);
|
||||
|
||||
return reticlePosition;
|
||||
}
|
||||
|
||||
public void SafelyDeleteTarget(){
|
||||
// gameObject.
|
||||
foreach (LockOnManager.ActiveLockOnTarget target in LockOnManager.Instance.activeTargets) {
|
||||
if (target.gameObject == this.gameObject) {
|
||||
GameObject clone = new GameObject{name = $"Target Clone of {gameObject.name}", transform = { position = transform.position}};
|
||||
|
||||
target.gameObject = clone;
|
||||
target.cinemachineTarget.Object = clone.transform;
|
||||
|
||||
LockOnManager.Instance.QueueTargetRemoval(clone, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class PlayerCamera : MonoBehaviour{
|
||||
void Start(){
|
||||
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void LateUpdate(){
|
||||
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/Units/PlayerCamera.cs.meta
Normal file
2
Assets/Scripts/Units/PlayerCamera.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d224dfedffdf96f4896aeee0ce605153
|
||||
120
Assets/Scripts/Units/PlayerControls.cs
Normal file
120
Assets/Scripts/Units/PlayerControls.cs
Normal file
@@ -0,0 +1,120 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.InputSystem;
|
||||
using UnityEngine.UIElements;
|
||||
using NodeCanvas;
|
||||
using NodeCanvas.Framework;
|
||||
using ParadoxNotion;
|
||||
using Reset;
|
||||
using Sirenix.OdinInspector;
|
||||
using Unity.Cinemachine;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
public class PlayerControls : MonoBehaviour{
|
||||
// References
|
||||
private Player thisPlayer;
|
||||
|
||||
private PlayerInput input;
|
||||
private SignalDefinition inputSignal;
|
||||
private SignalDefinition blockSignal;
|
||||
|
||||
// TODO: Turn these into accessors
|
||||
public Vector2 rawMoveInput;
|
||||
public Vector2 rawLookInput;
|
||||
|
||||
public GraphOwner graph;
|
||||
|
||||
void Awake(){
|
||||
|
||||
try {
|
||||
inputSignal = Resources.Load<SignalDefinition>("InputSignal");
|
||||
} catch (Exception e) {
|
||||
Debug.LogError($"Error finding the Input Signal defintion: {e.Message}");
|
||||
throw;
|
||||
}
|
||||
|
||||
try {
|
||||
blockSignal = Resources.Load<SignalDefinition>("BlockInputSignal");
|
||||
} catch (Exception e) {
|
||||
Debug.LogError($"Error finding the Input Signal defintion: {e.Message}");
|
||||
throw;
|
||||
}
|
||||
|
||||
thisPlayer = GetComponent<Player>();
|
||||
graph = GetComponent<GraphOwner>();
|
||||
input = GetComponent<PlayerInput>();
|
||||
|
||||
// Remove all devices from this user
|
||||
input.user.UnpairDevices();
|
||||
|
||||
// Add the delegates for each method
|
||||
foreach (InputAction action in input.actions) {
|
||||
action.started += SendInputSignal;
|
||||
action.canceled += SendInputSignal;
|
||||
action.performed += SendInputSignal;
|
||||
}
|
||||
}
|
||||
|
||||
// Remove the delegates for each method
|
||||
void OnDisable(){
|
||||
foreach (InputAction action in input.actions) {
|
||||
action.started -= SendInputSignal;
|
||||
action.canceled -= SendInputSignal;
|
||||
action.performed -= SendInputSignal;
|
||||
}
|
||||
}
|
||||
|
||||
// This will call the SignalInvoke for this type of Signal Defintion. CheckInput is the recieving end.
|
||||
public void SendInputSignal(InputAction.CallbackContext ctx){
|
||||
inputSignal.Invoke(transform, transform, false, new object[]{
|
||||
ctx.action,
|
||||
ctx.phase
|
||||
});
|
||||
}
|
||||
|
||||
public void SendInputBlock(string actionName){
|
||||
Debug.Log($"Sending block request...");
|
||||
blockSignal.Invoke(transform, transform, false, new object[]{actionName});
|
||||
}
|
||||
|
||||
public void OnMove(InputValue value){
|
||||
rawMoveInput.x = value.Get<Vector2>().x;
|
||||
rawMoveInput.y = value.Get<Vector2>().y;
|
||||
}
|
||||
|
||||
public void OnLook(InputValue value){
|
||||
rawLookInput.x = value.Get<Vector2>().x;
|
||||
rawLookInput.y = value.Get<Vector2>().y;
|
||||
|
||||
// GameManager.Camera.transform.Find("Cinemachine").GetComponent<CustomInputHandler>().Controllers[0].InputValue = rawLookInput.x * 200;
|
||||
// GameManager.Camera.transform.Find("Cinemachine").GetComponent<CustomInputHandler>().Controllers[1].InputValue = rawLookInput.y * 100;
|
||||
}
|
||||
|
||||
public void OnSprint(){
|
||||
graph.SendEvent<string>("InputEvent", "Sprint", null);
|
||||
}
|
||||
|
||||
public void OnJump(){
|
||||
graph.SendEvent<string>("InputEvent", "Jump", null);
|
||||
}
|
||||
|
||||
public void OnLockOn(){
|
||||
GetComponent<LockOnManager>().ChangeLockOnTarget();
|
||||
graph.SendEvent<string>("InputEvent", "LockOn", null);
|
||||
}
|
||||
|
||||
public void OnCancelLockOn(){
|
||||
GetComponent<LockOnManager>().RemoveMainTarget();
|
||||
graph.SendEvent<string>("InputEvent", "CancelLockOn", null);
|
||||
}
|
||||
|
||||
// public void OnGrapple(InputInteractionContext context){
|
||||
// if (context.control.IsPressed()) {
|
||||
// graph.SendEvent<string>("InputEvent", "GrappleDown", null);
|
||||
// } else {
|
||||
// graph.SendEvent<string>("InputEvent", "GrappleUp", null);
|
||||
// }
|
||||
// }
|
||||
}
|
||||
2
Assets/Scripts/Units/PlayerControls.cs.meta
Normal file
2
Assets/Scripts/Units/PlayerControls.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2d0c4f0666ff5f245bf2a135c782127b
|
||||
400
Assets/Scripts/Units/PlayerEnvironmentManager.cs
Normal file
400
Assets/Scripts/Units/PlayerEnvironmentManager.cs
Normal file
@@ -0,0 +1,400 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using Drawing;
|
||||
using Sirenix.OdinInspector;
|
||||
using Sirenix.Serialization;
|
||||
using Unity.Mathematics;
|
||||
using UnityEngine.Serialization;
|
||||
|
||||
[Serializable]
|
||||
public class EnvironmentObserver{
|
||||
enum LabelDrawingLocation{
|
||||
PlayerOffset,
|
||||
HitLocation,
|
||||
IntersectingLength,
|
||||
}
|
||||
|
||||
enum ObserverGizmoDrawingCondition{
|
||||
Always,
|
||||
OnlyActive,
|
||||
Never
|
||||
}
|
||||
|
||||
public enum CastType{
|
||||
Ray,
|
||||
BoxOverlap,
|
||||
SphereOverlap,
|
||||
BoxCast,
|
||||
SphereCast
|
||||
}
|
||||
|
||||
[PropertySpace(0, 5), LabelWidth(60)]
|
||||
public string label;
|
||||
[PropertySpace(0, 10), LabelWidth(60)]
|
||||
public CastType castType;
|
||||
|
||||
[Button(ButtonSizes.Large), GUIColor("@GetObserverStatusColorStatic(active, hit)"), PropertyOrder(-1), PropertySpace(5, 5)]
|
||||
public void Active(){
|
||||
active = !active;
|
||||
}
|
||||
|
||||
[HideInInspector]
|
||||
public bool active;
|
||||
|
||||
// Parameters for Cast cast types
|
||||
[FoldoutGroup("Settings")] [HideIf("@castType == CastType.BoxOverlap || castType == CastType.SphereOverlap")]
|
||||
public float length;
|
||||
[FoldoutGroup("Settings")] public Vector3 direction;
|
||||
[FoldoutGroup("Settings")] public Vector3 offset;
|
||||
[PropertySpace(0, 5), FoldoutGroup("Settings")] public LayerMask ignoreLayers = ~0;
|
||||
|
||||
[FoldoutGroup("Settings")] [ShowIf("@castType == CastType.BoxOverlap || castType == CastType.SphereOverlap")]
|
||||
public List<Collider> ignoreObjects = new List<Collider>();
|
||||
|
||||
[FoldoutGroup("Settings")] [ShowIf("@castType == CastType.BoxOverlap || castType == CastType.SphereOverlap")]
|
||||
public bool dontIgnoreSelf;
|
||||
|
||||
[ShowIfGroup("Settings/SpheresOnly", VisibleIf = "@castType == CastType.SphereCast || castType == CastType.SphereOverlap")]
|
||||
[FoldoutGroup("Settings")] public float width;
|
||||
|
||||
// Parameters for Overlap cast types
|
||||
[FoldoutGroup("Settings")]
|
||||
[ShowIfGroup("Settings/BoxesOnly", VisibleIf = "@castType == CastType.BoxCast || castType == CastType.BoxOverlap")]
|
||||
public Vector3 size;
|
||||
|
||||
[ShowIfGroup("Settings/BoxesOnly")]
|
||||
public Vector3 rotation;
|
||||
|
||||
[HideInInspector]
|
||||
public RaycastHit hit;
|
||||
|
||||
[HideInInspector]
|
||||
public Collider[] overlapHits;
|
||||
|
||||
[FoldoutGroup("Text")]
|
||||
[BoxGroup("Text/Label")] public bool drawLabel;
|
||||
[ShowInInspector, SerializeField] [BoxGroup("Text/Label")] LabelDrawingLocation labelTextLocation;
|
||||
[BoxGroup("Text/Label")] public float labelSize;
|
||||
[BoxGroup("Text/Label")] public Vector3 labelLocationOffset;
|
||||
[BoxGroup("Text/Label")] public Vector3 labelRotationOffset;
|
||||
|
||||
[BoxGroup("Text/Hit")] public bool drawHitName;
|
||||
[ShowInInspector, SerializeField] [BoxGroup("Text/Hit")] LabelDrawingLocation hitTextLocation;
|
||||
[BoxGroup("Text/Hit")] public float hitTextSize;
|
||||
[BoxGroup("Text/Hit")] public Vector3 hitLocationOffset;
|
||||
[BoxGroup("Text/Hit")] public Vector3 hitRotationOffset;
|
||||
[FoldoutGroup("Text"), SerializeField, ShowInInspector] ObserverGizmoDrawingCondition gizmoDrawingCondition;
|
||||
|
||||
[SerializeReference, PropertySpace(5, 5)]
|
||||
public List<EnvironmentObserver> children;
|
||||
|
||||
// NOTE: I had a ref for a RaycastHit here that would correspond to hit but idk if it's needed.
|
||||
public bool Evaluate(GameObject source){
|
||||
if (active) {
|
||||
// Remove player's layer from LayerMask.
|
||||
ignoreLayers -= source.layer;
|
||||
|
||||
// Set some of the variables used later during casting
|
||||
Vector3 relativeStart = source.transform.position + offset;
|
||||
Vector3 relativeStartWithRotation = source.transform.position + source.transform.rotation * offset ;
|
||||
|
||||
switch (castType) {
|
||||
case CastType.Ray:
|
||||
Physics.Raycast(relativeStart, source.transform.rotation * direction, out hit, length, ignoreLayers);
|
||||
break;
|
||||
case CastType.BoxOverlap:
|
||||
// Create original box overlap
|
||||
Collider[] originalOverlap = Physics.OverlapBox(relativeStartWithRotation, size / 2f,
|
||||
source.transform.rotation * Quaternion.Euler(rotation), ignoreLayers);
|
||||
|
||||
// Convert to a list for editing
|
||||
List<Collider> collidersAsList = new List<Collider>();
|
||||
collidersAsList.AddRange(originalOverlap);
|
||||
|
||||
// Remove any specifically specified objects
|
||||
foreach (Collider ignoredObject in ignoreObjects) {
|
||||
if (collidersAsList.Contains(ignoredObject)) {
|
||||
collidersAsList.Remove(ignoredObject);
|
||||
}
|
||||
}
|
||||
|
||||
// Remove the source but only if requested
|
||||
if (!dontIgnoreSelf) {
|
||||
if (collidersAsList.Contains(source.GetComponent<Collider>())) {
|
||||
collidersAsList.Remove(source.GetComponent<Collider>());
|
||||
}
|
||||
}
|
||||
|
||||
// Send back to an array and done
|
||||
overlapHits = collidersAsList.ToArray();
|
||||
|
||||
if (overlapHits.Length > 0) {
|
||||
return true;
|
||||
};
|
||||
|
||||
break;
|
||||
case CastType.SphereOverlap:
|
||||
break;
|
||||
case CastType.BoxCast:
|
||||
// TODO: Make this not an if statement. Check that it works with NodeCanvas first
|
||||
if (Physics.BoxCast(relativeStartWithRotation, size / 2f,
|
||||
source.transform.rotation * Quaternion.Euler(rotation) * direction,
|
||||
out hit, source.transform.rotation * Quaternion.Euler(rotation), length,
|
||||
ignoreLayers)
|
||||
) {
|
||||
};
|
||||
break;
|
||||
case CastType.SphereCast:
|
||||
// TODO: Make this not an if statement. Check that it works with NodeCanvas first
|
||||
if (Physics.SphereCast(relativeStartWithRotation, width / 2f,
|
||||
source.transform.rotation * Quaternion.Euler(rotation) * direction,
|
||||
out hit, length,
|
||||
ignoreLayers)
|
||||
) {
|
||||
};
|
||||
break;
|
||||
}
|
||||
|
||||
if (hit.transform != null) {
|
||||
if (hit.transform.GetComponent<IInteractable>() != null) {
|
||||
hit.transform.GetComponent<IInteractable>().OnObserverDetected(this);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void DrawObserverGizmo(GameObject source, bool drawAnyways = false){
|
||||
if (!drawAnyways){
|
||||
if (gizmoDrawingCondition == ObserverGizmoDrawingCondition.Never || (gizmoDrawingCondition == ObserverGizmoDrawingCondition.OnlyActive ! & active)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Vector3 relativeStart = source.transform.position + offset;
|
||||
Vector3 relativeStartWithRotation = source.transform.position + source.transform.rotation * (offset);
|
||||
|
||||
// Setup the variables for boxcast, spherecast, etc
|
||||
// Create an offset start point for the center of the wirebox, since gizmos are drawn with their pivot in the center.
|
||||
Vector3 offsetWithRotationAndLength;
|
||||
if (direction == Vector3.zero) {
|
||||
offsetWithRotationAndLength = Quaternion.Euler(rotation) * (Vector3.forward * (length / 2));
|
||||
} else {
|
||||
offsetWithRotationAndLength = Quaternion.LookRotation(direction) * Quaternion.Euler(rotation) * (Vector3.forward * (length / 2));
|
||||
}
|
||||
|
||||
Vector3 offsetFromCenter = relativeStartWithRotation + source.transform.rotation * offsetWithRotationAndLength;
|
||||
|
||||
// Also create a rotation for use with the gizmos. Mainly just to shorten the lines
|
||||
Quaternion gizmosRotation;
|
||||
|
||||
if (direction == Vector3.zero) {
|
||||
gizmosRotation = source.transform.rotation * Quaternion.Euler(rotation);
|
||||
} else {
|
||||
gizmosRotation = source.transform.rotation * Quaternion.LookRotation(direction) * Quaternion.Euler(rotation);
|
||||
}
|
||||
|
||||
Color gizmoColor = Evaluate(source) ? Color.green : Color.red;
|
||||
gizmoColor = active ? gizmoColor : Color.gray;
|
||||
|
||||
using (Draw.ingame.WithColor(gizmoColor)){
|
||||
switch (castType) {
|
||||
case CastType.Ray:
|
||||
Draw.ingame.Line(relativeStart, relativeStart + (source.transform.rotation * direction.normalized) * length);
|
||||
break;
|
||||
case CastType.BoxOverlap:
|
||||
Draw.ingame.WireBox(relativeStartWithRotation, source.transform.rotation * Quaternion.Euler(rotation), size);
|
||||
break;
|
||||
case CastType.SphereCast:
|
||||
Draw.ingame.SolidCircle(relativeStartWithRotation, relativeStartWithRotation - Camera.main.transform.position, width * 1, gizmoColor.Alpha(.5f));
|
||||
Draw.ingame.WireCapsule(relativeStartWithRotation, relativeStartWithRotation + gizmosRotation * (Vector3.forward * (length - width / 2)), width);
|
||||
break;
|
||||
case CastType.BoxCast:
|
||||
// Draw the gizmos for the boxcast
|
||||
Draw.ingame.WireBox(offsetFromCenter, gizmosRotation, new float3(size.x, size.y, length));
|
||||
Draw.ingame.SolidBox(relativeStartWithRotation, gizmosRotation, size, gizmoColor.Alpha(.1f));
|
||||
|
||||
Draw.ingame.WireBox(relativeStartWithRotation, gizmosRotation, size);
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
|
||||
Draw.ingame.SolidCircle(relativeStartWithRotation, relativeStartWithRotation - Camera.main.transform.position, .4f);
|
||||
Draw.ingame.SolidCircle(hit.point, hit.point - Camera.main.transform.position, .4f);
|
||||
|
||||
// Set up variables for label (not hit name)
|
||||
Vector3 labelStartPos = Vector3.zero;
|
||||
switch (labelTextLocation) {
|
||||
case LabelDrawingLocation.PlayerOffset:
|
||||
labelStartPos = source.transform.position;
|
||||
break;
|
||||
case LabelDrawingLocation.IntersectingLength:
|
||||
labelStartPos = offsetFromCenter;
|
||||
break;
|
||||
case LabelDrawingLocation.HitLocation:{
|
||||
if (hit.transform != null) {
|
||||
labelStartPos = hit.point;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Draw label
|
||||
if (drawLabel) {
|
||||
Draw.ingame.Label3D(
|
||||
labelStartPos + labelLocationOffset,
|
||||
gizmosRotation * Quaternion.Euler(labelRotationOffset),
|
||||
label,
|
||||
labelSize,
|
||||
LabelAlignment.MiddleLeft,
|
||||
gizmoColor
|
||||
);
|
||||
}
|
||||
|
||||
// Set up variables for hit name
|
||||
// Since the label is already drawn just use the previous startPos
|
||||
switch (labelTextLocation) {
|
||||
case LabelDrawingLocation.PlayerOffset:
|
||||
labelStartPos = source.transform.position;
|
||||
break;
|
||||
case LabelDrawingLocation.IntersectingLength:
|
||||
labelStartPos = offsetFromCenter;
|
||||
break;
|
||||
case LabelDrawingLocation.HitLocation:{
|
||||
if (hit.transform != null) {
|
||||
labelStartPos = hit.point;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Draw hitname
|
||||
if (drawLabel) {
|
||||
Draw.ingame.Label3D(
|
||||
labelStartPos + labelLocationOffset,
|
||||
gizmosRotation * Quaternion.Euler(labelRotationOffset),
|
||||
label,
|
||||
hitTextSize,
|
||||
LabelAlignment.MiddleLeft,
|
||||
gizmoColor
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static Color GetObserverStatusColorStatic(bool active, RaycastHit hit){
|
||||
if (active) {
|
||||
if (hit.Equals(default(RaycastHit))) {
|
||||
return Color.green;
|
||||
}
|
||||
|
||||
return Color.red;
|
||||
}
|
||||
|
||||
return Color.gray;
|
||||
}
|
||||
}
|
||||
|
||||
public class PlayerEnvironmentManager : MonoBehaviour{
|
||||
[OdinSerialize]
|
||||
public List<EnvironmentObserver> observers;
|
||||
|
||||
void Start(){
|
||||
CheckDuplicateLabels(observers);
|
||||
}
|
||||
|
||||
// TODO: Not working.
|
||||
void CheckDuplicateLabels(List<EnvironmentObserver> sourceList){
|
||||
foreach (EnvironmentObserver sourceObserver in observers) {
|
||||
foreach (EnvironmentObserver observer in sourceList) {
|
||||
if (sourceObserver == observer) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (sourceObserver.label == observer.label) {
|
||||
Debug.LogError($"Duplicate label found in observer: {observer.label} is in use multiple times");
|
||||
}
|
||||
|
||||
if (observer.children != null && observer.children.Count > 0) {
|
||||
CheckDuplicateLabels(observer.children);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool EvaluateFromString(string searchLabel, List<EnvironmentObserver> observerList = null){
|
||||
List<EnvironmentObserver> listToUse = observers;
|
||||
|
||||
if (observerList != null) {
|
||||
listToUse = observerList;
|
||||
}
|
||||
|
||||
foreach (EnvironmentObserver observer in listToUse) {
|
||||
if (observer.label == searchLabel) {
|
||||
return observer.Evaluate(gameObject);
|
||||
}
|
||||
|
||||
if (observer.children != null && observer.children.Count > 0) {
|
||||
foreach (EnvironmentObserver childObserver in observer.children) {
|
||||
EvaluateFromString(searchLabel, childObserver.children);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public EnvironmentObserver FindObserverFromString(string searchLabel, List<EnvironmentObserver> observerList = null){
|
||||
List<EnvironmentObserver> listToUse = observers;
|
||||
|
||||
if (observerList != null) {
|
||||
listToUse = observerList;
|
||||
}
|
||||
|
||||
foreach (EnvironmentObserver observer in listToUse) {
|
||||
if (observer.label == searchLabel) {
|
||||
return observer;
|
||||
}
|
||||
|
||||
if (observer.children != null && observer.children.Count > 0) {
|
||||
foreach (EnvironmentObserver childObserver in observer.children) {
|
||||
FindObserverFromString(searchLabel, childObserver.children);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
void Update(){
|
||||
}
|
||||
|
||||
void LateUpdate(){
|
||||
// Draw Gizmos
|
||||
foreach (EnvironmentObserver observer in observers) {
|
||||
observer.DrawObserverGizmo(gameObject);
|
||||
|
||||
if (observer.children != null && observer.children.Count > 0) {
|
||||
foreach (EnvironmentObserver childObserver in observer.children) {
|
||||
childObserver.DrawObserverGizmo(gameObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Clear hit
|
||||
foreach (EnvironmentObserver observer in observers) {
|
||||
observer.hit = default;
|
||||
|
||||
if (observer.children != null && observer.children.Count > 0) {
|
||||
foreach (EnvironmentObserver childObserver in observer.children) {
|
||||
childObserver.hit = default;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/Units/PlayerEnvironmentManager.cs.meta
Normal file
2
Assets/Scripts/Units/PlayerEnvironmentManager.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7a8c0593fef54844383c2f154cf8806c
|
||||
10
Assets/Scripts/Units/PlayerFacingDirection.cs
Normal file
10
Assets/Scripts/Units/PlayerFacingDirection.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
namespace Reset.Units{
|
||||
public enum PlayerFacingDirection{
|
||||
TowardsTarget = 0,
|
||||
MatchInput,
|
||||
MatchCamera,
|
||||
Static,
|
||||
Momentum,
|
||||
SpecifiedDirection
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Units/PlayerFacingDirection.cs.meta
Normal file
3
Assets/Scripts/Units/PlayerFacingDirection.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 81d909774c8e4b66be6e96fd13f9bff4
|
||||
timeCreated: 1758478092
|
||||
57
Assets/Scripts/Units/ResolvedMovement.cs
Normal file
57
Assets/Scripts/Units/ResolvedMovement.cs
Normal file
@@ -0,0 +1,57 @@
|
||||
using System;
|
||||
using Reset.Core.Tools;
|
||||
using Sirenix.OdinInspector;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Reset.Units{
|
||||
public class ResolvedMovement{
|
||||
public struct MoveDirection{
|
||||
private Transform owner;
|
||||
|
||||
// Both are in world space, and translated to local
|
||||
private Vector2 _moveRaw;
|
||||
private Vector2 _moveDir;
|
||||
|
||||
[ShowInInspector]
|
||||
public Vector2 World{
|
||||
get{
|
||||
DebugOverlayDrawer.ChangeValue("Movement", "_moveDir", _moveDir);
|
||||
return _moveDir;
|
||||
}
|
||||
set{
|
||||
_moveDir = value;
|
||||
}
|
||||
}
|
||||
|
||||
[ShowInInspector]
|
||||
public Vector2 Local => owner.InverseTransformDirection(_moveDir.ToVector3()).ToVector2();
|
||||
|
||||
[ShowInInspector, PropertySpace(5)]
|
||||
public Vector2 RawWorld{
|
||||
get{
|
||||
DebugOverlayDrawer.ChangeValue("Movement", "_moveRaw", _moveRaw);
|
||||
// return owner.TransformDirection(_moveDir.ToVector3()).ToVector2();
|
||||
return _moveRaw;
|
||||
}
|
||||
set{
|
||||
_moveRaw = value;
|
||||
}
|
||||
}
|
||||
|
||||
[ShowInInspector]
|
||||
public Vector2 RawLocal => owner.InverseTransformDirection(_moveRaw.ToVector3()).ToVector2();
|
||||
|
||||
public MoveDirection(Transform ownerTransform){
|
||||
owner = ownerTransform;
|
||||
_moveDir = Vector2.zero;
|
||||
_moveRaw = Vector2.zero;
|
||||
}
|
||||
}
|
||||
|
||||
[ShowInInspector, InlineProperty, BoxGroup("Direction"), HideLabel] public MoveDirection moveDirection;
|
||||
public float moveSpeed;
|
||||
public Quaternion rotation;
|
||||
public float rotationSpeed;
|
||||
public float gravity;
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Units/ResolvedMovement.cs.meta
Normal file
3
Assets/Scripts/Units/ResolvedMovement.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d663059052094322bff98f9ed2839fd9
|
||||
timeCreated: 1758478092
|
||||
108
Assets/Scripts/Units/SettingValue.cs
Normal file
108
Assets/Scripts/Units/SettingValue.cs
Normal file
@@ -0,0 +1,108 @@
|
||||
using System;
|
||||
using Sirenix.OdinInspector;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Serialization;
|
||||
|
||||
public interface IResettableSettingValue{
|
||||
public void Verify();
|
||||
public void SmoothAndEase();
|
||||
public void Initialize();
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class SettingValue<T> : IResettableSettingValue{
|
||||
[HorizontalGroup("Settings", width: .3f), VerticalGroup("Settings/Value"), BoxGroup("Settings/Value/Value"), LabelText("Target")]
|
||||
public T targetValue;
|
||||
[HorizontalGroup("Settings"), VerticalGroup("Settings/Value"), BoxGroup("Settings/Value/Value"), LabelText("Current")]
|
||||
public T currentValue;
|
||||
[HorizontalGroup("Settings"), VerticalGroup("Settings/Smoothing"), BoxGroup("Settings/Smoothing/Smoothing"), LabelText("Target"), ShowIf("@IsSmoothable()")]
|
||||
public float targetSmoothing; // Smoothing changes how fast the value is changed.
|
||||
[HorizontalGroup("Settings"), VerticalGroup("Settings/Easing"), BoxGroup("Settings/Easing/Easing"), LabelText("Target"), ShowIf("@IsSmoothable()")]
|
||||
public float targetEasing; // Easing changes how fast smoothing is changed, when given a new value.
|
||||
|
||||
public T Value{
|
||||
get => currentValue;
|
||||
set => targetValue = value;
|
||||
}
|
||||
[HorizontalGroup("Settings"), VerticalGroup("Settings/Smoothing"), BoxGroup("Settings/Smoothing/Smoothing"), LabelText("Current"), ShowIf("@IsSmoothable()")]
|
||||
public float currentSmoothing;
|
||||
[HorizontalGroup("Settings"), VerticalGroup("Settings/Value"), BoxGroup("Settings/Value/Value"), LabelText("Default")]
|
||||
public T defaultValue;
|
||||
[HorizontalGroup("Settings"), VerticalGroup("Settings/Smoothing"), BoxGroup("Settings/Smoothing/Smoothing"), LabelText("Default"), ShowIf("@IsSmoothable()")]
|
||||
public float defaultSmoothing;
|
||||
[HorizontalGroup("Settings"), VerticalGroup("Settings/Easing"), BoxGroup("Settings/Easing/Easing"), LabelText("Default"), ShowIf("@IsSmoothable()")]
|
||||
public float defaultEasing;
|
||||
|
||||
private float refVelFloat; // For use with SmoothDamp
|
||||
private Vector3 refVelV3; // For use with SmoothDamp
|
||||
private Vector2 refVelV2; // For use with SmoothDamp
|
||||
|
||||
private bool verified;
|
||||
|
||||
bool IsSmoothable(){
|
||||
return (typeof(T) == typeof(float) || typeof(T) == typeof(Vector2) || typeof(T) == typeof(Vector3) || typeof(T) == typeof(Vector4) || typeof(T) == typeof(Quaternion) );
|
||||
}
|
||||
|
||||
public SettingValue(T initValue, float defaultEasing = 2f, float defaultSmoothing = 1f){
|
||||
targetValue = initValue;
|
||||
|
||||
defaultValue = initValue;
|
||||
|
||||
this.defaultSmoothing = defaultSmoothing;
|
||||
this.defaultEasing = defaultEasing;
|
||||
|
||||
targetEasing = defaultEasing;
|
||||
targetSmoothing = defaultSmoothing;
|
||||
|
||||
currentSmoothing = targetSmoothing;
|
||||
currentValue = targetValue;
|
||||
|
||||
refVelFloat = 0;
|
||||
refVelV3 = default;
|
||||
refVelV2 = default;
|
||||
}
|
||||
|
||||
public void Verify(){
|
||||
if (targetValue.Equals(currentValue) == false) {
|
||||
Debug.LogWarning($"A SettingValue ({this}) doesn't have its current and target value matching. This should have been set!");
|
||||
}
|
||||
|
||||
verified = true;
|
||||
}
|
||||
|
||||
public void SmoothAndEase(){
|
||||
if (!verified) {
|
||||
Debug.LogWarning($"A SettingValue ({this}) wasn't verified before being smoothed and eased. What's up with that?");
|
||||
}
|
||||
|
||||
currentSmoothing = Mathf.MoveTowards(currentSmoothing, targetSmoothing, targetEasing * targetEasing * Time.deltaTime);
|
||||
|
||||
if (typeof(T) == typeof(float)) {
|
||||
currentValue = (T)(object)Mathf.SmoothDamp((float)(object)currentValue, (float)(object)targetValue, ref refVelFloat, currentSmoothing * Time.deltaTime);
|
||||
}
|
||||
|
||||
if (typeof(T) == typeof(Vector2)) {
|
||||
currentValue = (T)(object)Vector2.SmoothDamp((Vector2)(object)currentValue, (Vector2)(object)targetValue, ref refVelV2, currentSmoothing * currentSmoothing * Time.deltaTime);
|
||||
}
|
||||
|
||||
if (typeof(T) == typeof(Vector3)) {
|
||||
currentValue = (T)(object)Vector3.SmoothDamp((Vector3)(object)currentValue, (Vector3)(object)targetValue, ref refVelV3, currentSmoothing * currentSmoothing * Time.deltaTime);
|
||||
}
|
||||
|
||||
if (typeof(T) == typeof(Vector4) || typeof(T) == typeof(Quaternion)) {
|
||||
// I have... zero clue if this will work. There is no Vector4 or Quaternion SmoothDamp
|
||||
Vector3 v3value = Vector3.SmoothDamp((Vector4)(object)currentValue, (Vector4)(object)targetValue, ref refVelV3, currentSmoothing * currentSmoothing * Time.deltaTime);
|
||||
float v4value = Mathf.SmoothDamp(((Vector4)(object)currentValue).z, ((Vector4)(object)targetValue).z, ref refVelFloat, currentSmoothing * currentSmoothing * Time.deltaTime);
|
||||
|
||||
currentValue = (T)(object)new Vector4(v3value.x, v3value.y, v3value.z, v4value);
|
||||
}
|
||||
}
|
||||
|
||||
public void Initialize(){
|
||||
currentValue = targetValue;
|
||||
defaultValue = targetValue;
|
||||
defaultSmoothing = targetSmoothing;
|
||||
defaultEasing = targetEasing;
|
||||
currentSmoothing = targetSmoothing;
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Units/SettingValue.cs.meta
Normal file
3
Assets/Scripts/Units/SettingValue.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 03e2aa4743404e9fbf8b14033c5eda7b
|
||||
timeCreated: 1758126336
|
||||
4
Assets/Scripts/Units/Unit.cs
Normal file
4
Assets/Scripts/Units/Unit.cs
Normal file
@@ -0,0 +1,4 @@
|
||||
using Unity.Netcode;
|
||||
|
||||
public class Unit : NetworkBehaviour{
|
||||
}
|
||||
3
Assets/Scripts/Units/Unit.cs.meta
Normal file
3
Assets/Scripts/Units/Unit.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d9f5c0c9bf384882925c15b3c93fff1b
|
||||
timeCreated: 1759554015
|
||||
62
Assets/Scripts/Units/UnitMovementData.cs
Normal file
62
Assets/Scripts/Units/UnitMovementData.cs
Normal file
@@ -0,0 +1,62 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using ParadoxNotion.Design;
|
||||
using Sirenix.OdinInspector;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Reset.Units{
|
||||
[Serializable]
|
||||
public class UnitMovementData{
|
||||
// Movement Direction
|
||||
[Title("Direction Changing Softeness"), HideLabel, InlineProperty] public SettingValue<float> directionChangingSoftness = new SettingValue<float>(1f, defaultSmoothing: 1f);
|
||||
[Title("Direction Spinning Hardness"), HideLabel, InlineProperty] public SettingValue<float> directionSpinningHardness = new SettingValue<float>(3f, defaultSmoothing: 1f);
|
||||
[Title("Directoon Spinning Speed"), HideLabel, InlineProperty] public SettingValue<float> directionSpinningSpeed= new SettingValue<float>(3f, defaultSmoothing: 1f);
|
||||
|
||||
[SliderField(0,1)]
|
||||
[Title("Air Direction Decay"), HideLabel, InlineProperty] public SettingValue<float> airDirectionDecay = new SettingValue<float>(1f); // TODO: Check default value
|
||||
|
||||
// Move Speed
|
||||
[Title("Acceleration"), HideLabel, InlineProperty] public SettingValue<float> acceleration = new SettingValue<float>(5f);
|
||||
[Title("Deacceleration"), HideLabel, InlineProperty] public SettingValue<float> deacceleration = new SettingValue<float>(5f);
|
||||
[Title("Move Speed"), HideLabel, InlineProperty] public SettingValue<float> moveSpeed = new SettingValue<float>(15f, defaultSmoothing: 10f);
|
||||
|
||||
// Jumping
|
||||
// [Title("Jump Power"), HideLabel, InlineProperty] [ShowInInspector] public SettingValue<float> jumpPower = new SettingValue<float>(0f);
|
||||
// [Title("Move Smoothing"), HideLabel, InlineProperty] public SettingValue<float> jumpPowerDecay = new SettingValue<float>(3f); // TODO: Check default value
|
||||
|
||||
// Gravity
|
||||
[Title("Gravity Power"), HideLabel, InlineProperty] [ShowInInspector] public SettingValue<float> gravityPower = new SettingValue<float>(1f);
|
||||
[Title("Gravity Max"), HideLabel, InlineProperty] public SettingValue<float> gravityMax = new SettingValue<float>(8f);
|
||||
[Title("Gravity Acceleration"), HideLabel, InlineProperty] public SettingValue<float> gravityAcceleration = new SettingValue<float>(1f);
|
||||
[Title("Gravity Scale"), HideLabel, InlineProperty] public SettingValue<float> gravityScale = new SettingValue<float>(1f);
|
||||
|
||||
// Rotation
|
||||
[Title("Rotate Facing"), HideLabel, InlineProperty] public SettingValue<PlayerFacingDirection> facingDirection = new SettingValue<PlayerFacingDirection>(initValue: PlayerFacingDirection.Momentum);
|
||||
[Title("Rotation Speed"), HideLabel, InlineProperty] public SettingValue<float> rotationSpeed = new SettingValue<float>(5f);
|
||||
|
||||
|
||||
public List<IResettableSettingValue> GetAllSettings(){
|
||||
var outputList = new List<IResettableSettingValue>();
|
||||
|
||||
IResettableSettingValue[] settings = {
|
||||
directionChangingSoftness,
|
||||
directionSpinningHardness,
|
||||
directionSpinningSpeed,
|
||||
acceleration,
|
||||
deacceleration,
|
||||
airDirectionDecay,
|
||||
moveSpeed,
|
||||
gravityPower,
|
||||
gravityMax,
|
||||
gravityAcceleration,
|
||||
gravityScale,
|
||||
facingDirection,
|
||||
rotationSpeed,
|
||||
};
|
||||
|
||||
outputList.AddRange(settings);
|
||||
|
||||
return outputList;
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Units/UnitMovementData.cs.meta
Normal file
3
Assets/Scripts/Units/UnitMovementData.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7f5d86c96bcf450b888da32d1cf253e7
|
||||
timeCreated: 1758478092
|
||||
326
Assets/Scripts/Units/UnitMovementHandler.cs
Normal file
326
Assets/Scripts/Units/UnitMovementHandler.cs
Normal file
@@ -0,0 +1,326 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using Reset.Core.Tools;
|
||||
using Sirenix.OdinInspector;
|
||||
|
||||
namespace Reset.Units{
|
||||
public class UnitMovementHandler : MonoBehaviour{
|
||||
[ShowInInspector, InlineProperty, HideLabel, FoldoutGroup("Resolved Movement", expanded: true)]
|
||||
public ResolvedMovement resolvedMovement;
|
||||
|
||||
// SmoothDamp Velocities
|
||||
private Vector2 refVelocityDirectionChangingHardness;
|
||||
|
||||
// Smoothing Values
|
||||
private float directionChangeDotLerp;
|
||||
private Vector3 moveSmoothVelocityRef;
|
||||
private float gravitySmoothVelocityRef;
|
||||
|
||||
// References
|
||||
private CharacterController controller;
|
||||
private PlayerControls controls;
|
||||
private LockOnManager lockOnManager;
|
||||
|
||||
// Movement Data
|
||||
[ShowInInspector, PropertyOrder(2), FoldoutGroup("Movement Data", expanded: true), InlineProperty, HideLabel] public UnitMovementData data = new();
|
||||
|
||||
// Other
|
||||
public Vector3 specifiedRotation; // Used for locking a specific direction
|
||||
|
||||
void Awake(){
|
||||
controller = GetComponent<CharacterController>();
|
||||
controls = GetComponent<PlayerControls>();
|
||||
lockOnManager = GetComponent<LockOnManager>();
|
||||
|
||||
InitAllSettings();
|
||||
}
|
||||
|
||||
void Start(){
|
||||
resolvedMovement = new ResolvedMovement{
|
||||
moveDirection = new ResolvedMovement.MoveDirection(transform)
|
||||
};
|
||||
}
|
||||
|
||||
void Update(){
|
||||
SmoothAllSettings();
|
||||
|
||||
UpdateCurrentDirection();
|
||||
UpdateCurrentGravity();
|
||||
UpdateCurrentSpeed();
|
||||
UpdateCurrentRotation();
|
||||
|
||||
// Apply movement
|
||||
DoMovement(resolvedMovement.moveDirection.World, resolvedMovement.gravity, resolvedMovement.moveSpeed, data.gravityScale.Value);
|
||||
DebugOverlayDrawer.ChangeValue("Movement", "Move Direction (Local)", resolvedMovement.moveDirection.Local);
|
||||
DebugOverlayDrawer.ChangeValue("Movement", "Move Direction (World)", resolvedMovement.moveDirection.World);
|
||||
}
|
||||
|
||||
// Update the direction, called every frame
|
||||
private void UpdateCurrentDirection(){
|
||||
// Get input value
|
||||
Vector2 targetDirection = new Vector2(controls.rawMoveInput.x, controls.rawMoveInput.y);
|
||||
|
||||
// Rotate input by camera rotation (instead of rotating the output direction by camera rotation)
|
||||
targetDirection = (Camera.main.transform.rotation * targetDirection.ToVector3()).ToVector2();
|
||||
|
||||
// Deadzone
|
||||
if (targetDirection.magnitude < .08f) {
|
||||
targetDirection = Vector2.zero;
|
||||
}
|
||||
|
||||
// Set Raw Direction (this is used by the camera later)
|
||||
resolvedMovement.moveDirection.RawWorld = targetDirection;
|
||||
|
||||
// Get current direction
|
||||
Vector2 currentDirection = resolvedMovement.moveDirection.World;
|
||||
|
||||
// Also need to find the dot value of the current input versus the current move direction
|
||||
float switchedDirection = Vector3.Dot(targetDirection, currentDirection);
|
||||
float switchedDirectionRemapped = Mathf.Lerp(0, 1, switchedDirection);
|
||||
|
||||
directionChangeDotLerp = Mathf.Lerp(switchedDirection, switchedDirectionRemapped, data.directionSpinningHardness.Value * Time.deltaTime);
|
||||
DebugOverlayDrawer.ChangeValue("Movement", "Direction Change Dot", directionChangeDotLerp);
|
||||
|
||||
// Smooth movement. Use deaccel smoothing if the input magnitude is lower, and accel smoothing if it's higher
|
||||
// Also checks when grounded to only use Slerp on the ground
|
||||
Vector3 slerpedValue;
|
||||
Vector2 lerpedValue;
|
||||
Vector2 newDirection;
|
||||
|
||||
if (controller.isGrounded){
|
||||
slerpedValue = Vector3.Slerp(currentDirection, targetDirection, data.directionSpinningSpeed.Value * Time.deltaTime);
|
||||
lerpedValue = Vector2.SmoothDamp(currentDirection, targetDirection, ref refVelocityDirectionChangingHardness, data.directionChangingSoftness.Value * Time.deltaTime);
|
||||
|
||||
newDirection = Vector2.Lerp(slerpedValue, lerpedValue, directionChangeDotLerp);
|
||||
} else {
|
||||
newDirection = Vector2.SmoothDamp(currentDirection, targetDirection, ref refVelocityDirectionChangingHardness, data.directionChangingSoftness.Value * data.airDirectionDecay.Value * Time.deltaTime);
|
||||
}
|
||||
|
||||
// Commit the new direction
|
||||
resolvedMovement.moveDirection.World = newDirection;
|
||||
}
|
||||
|
||||
// Update the speed, called every frame
|
||||
private void UpdateCurrentSpeed(){
|
||||
// ""Smooth"" the speed
|
||||
float smoothedSpeed;
|
||||
|
||||
if (resolvedMovement.moveDirection.Local.magnitude < controls.rawMoveInput.magnitude) {
|
||||
smoothedSpeed = Mathf.MoveTowards(resolvedMovement.moveSpeed, data.moveSpeed.Value, data.acceleration.Value * Time.deltaTime);
|
||||
} else {
|
||||
smoothedSpeed = Mathf.MoveTowards(resolvedMovement.moveSpeed, 0f, data.deacceleration.Value * Time.deltaTime);
|
||||
}
|
||||
|
||||
// Commit the speed
|
||||
resolvedMovement.moveSpeed = smoothedSpeed;
|
||||
|
||||
DebugOverlayDrawer.ChangeValue("Movement", "Resolved Speed", resolvedMovement.moveSpeed);
|
||||
}
|
||||
|
||||
// Update the gravity, called every frame
|
||||
// NOTE: most gravity interactions, like when grounded or not, is now handled by the state machine
|
||||
private void UpdateCurrentGravity(){
|
||||
// Accelerate gravity
|
||||
if (!controller.isGrounded){
|
||||
resolvedMovement.gravity -= data.gravityAcceleration.Value * Time.deltaTime;
|
||||
}
|
||||
|
||||
// Create the final gravity value
|
||||
float gravityMoveDirection = Physics.gravity.y * resolvedMovement.gravity;
|
||||
}
|
||||
|
||||
// Update the rotation, called every frame
|
||||
private void UpdateCurrentRotation(){
|
||||
// Get input value
|
||||
Vector3 inputMovement = new Vector3(controls.rawMoveInput.x, 0f, controls.rawMoveInput.y);
|
||||
|
||||
Quaternion targetRotation = Quaternion.identity;
|
||||
// Switch the desired rotation based on current movement setting
|
||||
switch (data.facingDirection.Value) {
|
||||
// Just look at target
|
||||
case PlayerFacingDirection.TowardsTarget:
|
||||
// Look directly at the target
|
||||
if (lockOnManager.mainTarget == null) {
|
||||
Debug.LogError("Trying to rotate towards a target but there is no target. Not setting a rotation");
|
||||
targetRotation = transform.rotation;
|
||||
break;
|
||||
}
|
||||
|
||||
targetRotation = Quaternion.LookRotation(transform.position.DirectionTo(lockOnManager.mainTarget.gameObject.transform.position));
|
||||
break;
|
||||
case PlayerFacingDirection.Momentum:
|
||||
// Look towards the current direction the agent is moving
|
||||
if (inputMovement.magnitude > .05f){
|
||||
targetRotation = Quaternion.LookRotation(resolvedMovement.moveDirection.RawWorld.ToVector3(), Vector3.up);
|
||||
}
|
||||
break;
|
||||
case PlayerFacingDirection.MatchInput:
|
||||
// Look towards the input direction- similar to Momentum but snappier
|
||||
if (controls.rawMoveInput.magnitude < 0.05f) { break; }
|
||||
|
||||
targetRotation = Camera.main.transform.rotation * Quaternion.LookRotation(inputMovement);
|
||||
break;
|
||||
case PlayerFacingDirection.MatchCamera:
|
||||
// Look the same direction as the camera
|
||||
targetRotation = Quaternion.Euler(Camera.main.transform.rotation.eulerAngles.Flatten(0, null, 0));
|
||||
break;
|
||||
case PlayerFacingDirection.Static:
|
||||
// Don't change
|
||||
targetRotation = resolvedMovement.rotation;
|
||||
break;
|
||||
}
|
||||
|
||||
DebugOverlayDrawer.ChangeValue("Rotation", "Target Rotation", targetRotation.eulerAngles);
|
||||
|
||||
// Add the current input into the created rotation
|
||||
if (inputMovement.magnitude > .05) {
|
||||
resolvedMovement.rotation = targetRotation;
|
||||
} else if (data.facingDirection.Value == PlayerFacingDirection.MatchCamera) {
|
||||
resolvedMovement.rotation = targetRotation;
|
||||
}
|
||||
|
||||
// Apply rotation to the character
|
||||
transform.rotation = Quaternion.Slerp(transform.rotation, resolvedMovement.rotation, data.rotationSpeed.Value * Time.deltaTime).Flatten(0, null, 0);
|
||||
}
|
||||
|
||||
|
||||
// Custom move from input
|
||||
private void DoMovement(Vector2 moveDir, float gravDir, float speed, float gravityScale){
|
||||
// Seperate the different move directions. Additonal becomes it's own because it needs to be added independently of the other two
|
||||
Vector2 moveXZDir = moveDir;
|
||||
float moveYDir = gravDir;
|
||||
|
||||
// Add their related speeds
|
||||
moveXZDir *= speed * Time.deltaTime;
|
||||
moveYDir *= data.gravityScale.Value * Time.deltaTime;
|
||||
|
||||
// Construct the direction and move
|
||||
Vector3 finalDir = new Vector3(moveXZDir.x, moveYDir, moveXZDir.y);
|
||||
controller.Move(finalDir);
|
||||
}
|
||||
|
||||
// Setting absolute to true will cause the current gravity to snap to the new gravity value.
|
||||
// Keeping it false will make it apply additively to the current gravity. Both options use relativty for linear interpolation.
|
||||
public void SetNewGravity(float value, float relativity, bool absolute){ // new
|
||||
if (absolute){
|
||||
resolvedMovement.gravity = Mathf.Lerp(resolvedMovement.gravity, value, relativity);
|
||||
} else {
|
||||
resolvedMovement.gravity = Mathf.Lerp(resolvedMovement.gravity, resolvedMovement.gravity + value, relativity);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetNewDirection(Vector2 value, float relativity, bool absolute, Vector2 relativeTo = default, bool relativeToRotation = true){ // new
|
||||
Vector2 relativeValue;
|
||||
|
||||
if (relativeToRotation){
|
||||
relativeValue = (Quaternion.LookRotation(relativeTo.ToVector3()) * value.ToVector3()).ToVector2();
|
||||
} else {
|
||||
relativeValue = relativeTo + value;
|
||||
}
|
||||
|
||||
if (absolute){
|
||||
resolvedMovement.moveDirection.World = Vector2.Lerp(resolvedMovement.moveDirection.World, relativeValue, relativity);
|
||||
} else {
|
||||
resolvedMovement.moveDirection.World = Vector2.Lerp(resolvedMovement.moveDirection.World, resolvedMovement.moveDirection.World + relativeValue, relativity);
|
||||
}
|
||||
|
||||
Debug.Log(resolvedMovement.moveDirection.World);
|
||||
}
|
||||
|
||||
public void SetNewRawDirection(Vector2 value, float relativity, bool absolute, Vector2 relativeTo = default){ // new
|
||||
Vector2 relativeValue = relativeTo + value;
|
||||
|
||||
if (absolute){
|
||||
resolvedMovement.moveDirection.RawWorld = Vector2.Lerp(resolvedMovement.moveDirection.RawWorld, relativeValue, relativity);
|
||||
} else {
|
||||
resolvedMovement.moveDirection.RawWorld = Vector2.Lerp(resolvedMovement.moveDirection.RawWorld, resolvedMovement.moveDirection.RawWorld + relativeValue, relativity);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetNewSpeed(float value, float relativity, bool absolute, float relativeTo = Mathf.Infinity){ // new
|
||||
if (absolute){
|
||||
resolvedMovement.moveSpeed = Mathf.Lerp(resolvedMovement.moveSpeed, value, relativity);
|
||||
} else {
|
||||
resolvedMovement.moveSpeed = Mathf.Lerp(resolvedMovement.moveSpeed, resolvedMovement.moveSpeed + value, relativity);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetNewRotation(Vector3 value, float relativity, bool absolute, Vector3 relativeTo = default){ // new
|
||||
Quaternion valueAsQuaternion = Quaternion.LookRotation(value);
|
||||
|
||||
if (relativeTo != default) {
|
||||
valueAsQuaternion = Quaternion.LookRotation(relativeTo) * valueAsQuaternion;
|
||||
}
|
||||
|
||||
if (absolute){
|
||||
resolvedMovement.rotation = Quaternion.Lerp(resolvedMovement.rotation, valueAsQuaternion, relativity);
|
||||
} else {
|
||||
resolvedMovement.rotation = Quaternion.Lerp(resolvedMovement.rotation, resolvedMovement.rotation * valueAsQuaternion, relativity);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void SetSpecifiedRotation(Vector3 inputRotation){
|
||||
specifiedRotation = inputRotation;
|
||||
}
|
||||
|
||||
public Vector2 GetResolvedDirection(){
|
||||
return resolvedMovement.moveDirection.World;
|
||||
}
|
||||
|
||||
public Vector3 GetResolvedDirectionVector3(){
|
||||
return resolvedMovement.moveDirection.World.ToVector3();
|
||||
}
|
||||
|
||||
public float GetResolvedSpeed(){
|
||||
return resolvedMovement.moveSpeed;
|
||||
}
|
||||
|
||||
public float GetResolvedGravity(){
|
||||
return resolvedMovement.gravity;
|
||||
}
|
||||
|
||||
public Quaternion GetResolvedRotation(){
|
||||
return resolvedMovement.rotation;
|
||||
}
|
||||
|
||||
[Button("Initialize Settings", ButtonHeight = 30), PropertySpace(10,5 )]
|
||||
void InitAllSettings(){
|
||||
var settingsList = data.GetAllSettings();
|
||||
|
||||
foreach (IResettableSettingValue value in settingsList) {
|
||||
value.Initialize();
|
||||
value.Verify();
|
||||
}
|
||||
}
|
||||
|
||||
void SmoothAllSettings(){
|
||||
var settingsList = data.GetAllSettings();
|
||||
|
||||
foreach (IResettableSettingValue value in settingsList) {
|
||||
value.SmoothAndEase();
|
||||
}
|
||||
}
|
||||
|
||||
public void AddToCurrentDirection(Vector3 inputDirection, float power){ // Old
|
||||
Debug.LogError("Using an old movement command! Switch to one of the new alternatives!");
|
||||
}
|
||||
|
||||
public void SmoothToSpeed(float desiredSpeed, float smoothing){ // Old
|
||||
Debug.LogError("Using an old movement command! Switch to one of the new alternatives!");
|
||||
}
|
||||
|
||||
public void SetNewDirection(Vector3 inputDirection){ // NOTE: If smoothing desired add a default bool for smoothing maybe? // Old
|
||||
Debug.LogError("Using an old movement command! Switch to one of the new alternatives!");
|
||||
}
|
||||
|
||||
public void SetNewGravity(float value){
|
||||
Debug.LogError("Using an old movement command! Switch to one of the new alternatives!");
|
||||
}
|
||||
|
||||
public void OverwriteDirectionFromInput(Vector2 value, float priority, float speed = Mathf.Infinity){ // Old
|
||||
Debug.LogError("Using an old movement command! Switch to one of the new alternatives!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
11
Assets/Scripts/Units/UnitMovementHandler.cs.meta
Normal file
11
Assets/Scripts/Units/UnitMovementHandler.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b3b4e13d59527d1429a62dde97c6a001
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 50
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user