change: altered camera for smoother and more responsive lock-on (mainly jitter from the arbitrary target, locking rotation)

This commit is contained in:
Chris
2025-08-06 15:23:42 -04:00
parent fa2b7ea3ad
commit eb06a5d33c
13 changed files with 185 additions and 53 deletions

View File

@@ -1,14 +1,14 @@
using System;
using UnityEngine;
public class GenericLockOnTarget : MonoBehaviour, ILockOnTarget{
public float lockonTargetRadius{ get; set; } = 1f;
// Start is called once before the first execution of Update after the MonoBehaviour is created
void Start(){
public void OnTargetDelete(){
GetComponent<ILockOnTarget>().SafelyDeleteTarget();
}
void Update(){
void OnDestroy(){
OnTargetDelete();
}
}

View File

@@ -27,7 +27,7 @@ namespace NodeCanvas.Tasks.Actions {
public TransformProperty targetProperty;
[ParadoxNotion.Design.ShowIf("targetProperty", 0), Space(5)]
[ParadoxNotion.Design.ShowIf("targetProperty", 1), Space(5)]
public BBParameter<bool> forcePositionChange;
public BBParameter<Vector3> targetValue;

View File

@@ -36,6 +36,7 @@ public enum CameraSettingsToggle{
NoChange,
NewValue,
ResetValue,
RelativeValue, // Placeholder for using as altering existing value
}
public interface ICameraValueGroup{
@@ -121,7 +122,7 @@ public class BoolCameraValueGroupDrawer : ObjectDrawer<BoolCameraValueGroup> {
// Start the Vertical layout then add the label before adding a horizontal so the label will be on top of side-by-side options
GUILayout.BeginVertical();
GUILayout.Label(_instance.ToString(), labelOptions);
GUILayout.Label(_instance.label, labelOptions);
GUILayout.BeginHorizontal();
// Create the x settings enum
@@ -164,7 +165,7 @@ public class FloatCameraValueGroupDrawer : ObjectDrawer<FloatCameraValueGroup>
// Start the Vertical layout then add the label before adding a horizontal so the label will be on top of side-by-side options
GUILayout.BeginVertical();
GUILayout.Label(_instance.ToString(), labelOptions);
GUILayout.Label(_instance.label, labelOptions);
GUILayout.BeginHorizontal();
// Create the x settings enum
@@ -431,7 +432,9 @@ namespace NodeCanvas.Tasks.Actions {
UpdateFloatValue(axisLookXGain, ref CameraSettingsProcessor.values.axisLookGainX);
UpdateFloatValue(axisLookYGain, ref CameraSettingsProcessor.values.axisLookGainY);
UpdateBoolValue(enableXAxis, ref CameraSettingsProcessor.values.axisLookEnabledX);
UpdateBoolValue(enableYAxis, ref CameraSettingsProcessor.values.axisLookEnabledY);
EndAction(true);

View File

@@ -104,6 +104,9 @@ namespace Reset {
observer.DrawObserverGizmo(agent.gameObject, true);
}
if (check && !outputHit.isNoneOrNull) {
outputHit.value = observer.hit;
}
return check;
}
}

View File

@@ -19,6 +19,11 @@ namespace NodeCanvas.Tasks.Actions {
//Use for initialization. This is called only once in the lifetime of the task.
//Return null if init was successfull. Return an error string otherwise
protected override string info{
get{ return $"Decompose RaycastHit <b>{raycastHit}</b>"; }
}
protected override string OnInit() {
return null;
}

View File

@@ -0,0 +1,65 @@
using NodeCanvas.Framework;
using ParadoxNotion.Design;
using ParadoxNotion.Serialization.FullSerializer;
using UnityEngine;
using Logger = ParadoxNotion.Services.Logger;
namespace NodeCanvas.Tasks.Actions {
[Category("Reset")]
public class UpdateObjectCameraTracking : ActionTask<LockOnManager> {
public BBParameter<GameObject> relatedObject;
enum CameraTrackingTaskAction{
AddOrUpdate,
Remove
}
[ExposeField, fsSerializeAs, Space(5)]
CameraTrackingTaskAction action;
[ParadoxNotion.Design.ShowIf("action", 0)]
public BBParameter<float> weight;
[ParadoxNotion.Design.ShowIf("action", 0)]
public BBParameter<bool> isMain;
//Return null if init was successfull. Return an error string otherwise
protected override string OnInit() {
return null;
}
//This is called once each time the task is enabled.
//Call EndAction() to mark the action as finished, either in success or failure.
//EndAction can be called from anywhere.
protected override void OnExecute() {
if (relatedObject.isNull) {
Logger.LogError("There is no object for the camera to add to tracking. May have forgotten a reference/object probably destroyed?");
EndAction(false);
return;
}
if (action == CameraTrackingTaskAction.AddOrUpdate) {
agent.AddNewTarget(relatedObject.value, weight.value, isMain.value);
} else {
agent.QueueTargetRemoval(relatedObject.value);
}
EndAction(true);
}
//Called once per frame while the action is active.
protected override void OnUpdate() {
}
//Called when the task is disabled.
protected override void OnStop() {
}
//Called when the task is paused.
protected override void OnPause() {
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: c187e5f8e4ad16b42b10c10ea9fb8fd4

View File

@@ -11,12 +11,14 @@ using Vector2 = UnityEngine.Vector2;
using Vector3 = UnityEngine.Vector3;
public class LockOnManager : MonoBehaviour{
class ReferencedTarget{
public class ActiveLockOnTarget{
public GameObject gameObject;
public float targetWeight;
public float refVelocity;
public CinemachineTargetGroup.Target cinemachineTarget;
}
public static LockOnManager Instance;
// Lock On settings
[Space(5)] public float lockOnRange = 40f;
@@ -28,10 +30,9 @@ public class LockOnManager : MonoBehaviour{
[Space(10)]
[ShowInInspector]
ReferencedTarget mainTarget;
ActiveLockOnTarget mainTarget;
[ShowInInspector]
List<ReferencedTarget> activeTargets = new List<ReferencedTarget>();
public List<ActiveLockOnTarget> activeTargets = new List<ActiveLockOnTarget>();
[ReadOnly] public CinemachineTargetGroup.Target lockonTarget;
public CinemachineTargetGroup targetGroup;
@@ -45,11 +46,19 @@ public class LockOnManager : MonoBehaviour{
// Start is called once before the first execution of Update after the MonoBehaviour is created
void Start(){
// Save the player target object to track later
// Register as singleton
if (Instance == null) {
Instance = this;
} else {
this.enabled = false;
return;
}
// Quick check for things in lock-on target that aren't lock-onable
if (mainTarget != null && mainTarget.gameObject.GetComponent<ILockOnTarget>() == null) {
Debug.LogError($"Game Object {mainTarget.gameObject.name} does not implement the ILockOnTarget interface!");
mainTarget.gameObject.AddComponent<GenericLockOnTarget>();
Debug.LogWarning($"The object <b>{mainTarget.gameObject.name}</b> has no ILockOnTarget interface. This isn't hyper critical, but adding one as a GenericLockOnTarget anyways.");
}
elementRoot = lockOnDocument.rootVisualElement.Query<VisualElement>("LockOnGroup");
@@ -67,7 +76,8 @@ public class LockOnManager : MonoBehaviour{
void Update(){
if (mainTarget != null && mainTarget.gameObject.GetComponent<ILockOnTarget>() == null) {
Debug.LogError($"Game Object {mainTarget.gameObject.name} does not implement the ILockOnTarget interface!");
mainTarget.gameObject.AddComponent<GenericLockOnTarget>();
Debug.LogWarning($"The object <b>{mainTarget.gameObject.name}</b> has no ILockOnTarget interface. This isn't hyper critical, but adding one as a GenericLockOnTarget anyways.");
}
// Iterate through targets, pushing their Target Group weight towards their goal weight, or removing them if they get too low.
@@ -89,7 +99,7 @@ public class LockOnManager : MonoBehaviour{
}
}
IEnumerator RemoveFromTargetAtFrameEnd(ReferencedTarget target){
IEnumerator RemoveFromTargetAtFrameEnd(ActiveLockOnTarget target){
yield return new WaitForEndOfFrame();
activeTargets.Remove(target);
@@ -98,7 +108,7 @@ public class LockOnManager : MonoBehaviour{
public void AddNewTarget(GameObject targetObject, float targetWeight, bool isMain = false){
// Check that the target doesn't already exist- if it does, just change it's weight/make it main
foreach (ReferencedTarget target in activeTargets) {
foreach (ActiveLockOnTarget target in activeTargets) {
if (target.gameObject == targetObject) {
target.targetWeight = targetWeight;
@@ -111,7 +121,7 @@ public class LockOnManager : MonoBehaviour{
}
// If it doesn't exist in the list of targets, add it
ReferencedTarget newTarget = new ReferencedTarget{
ActiveLockOnTarget newTarget = new ActiveLockOnTarget{
gameObject = targetObject,
targetWeight = mainTargetWeight,
cinemachineTarget = new CinemachineTargetGroup.Target{
@@ -131,16 +141,32 @@ public class LockOnManager : MonoBehaviour{
targetGroup.Targets.Add(newTarget.cinemachineTarget);
}
public void QueueTargetRemoval(GameObject targetObject){
public void QueueTargetRemoval(GameObject targetObject, bool deleteAfterRemoved = false){
// Ostensibly removes targest by setting their target weight to 0. Update loop finds targets with no weight and reduces their impact on the camera
// After it smooths their current weight to 0, it removes them
activeTargets.Find(target => target.gameObject == targetObject).targetWeight = 0f;
if (deleteAfterRemoved) {
StartCoroutine(DeleteGameObjectPostRemoval(targetObject));
}
// Remove as main target if it is
if (mainTarget == activeTargets.Find(target => target.gameObject == targetObject)) {
mainTarget = null;
}
}
IEnumerator DeleteGameObjectPostRemoval(GameObject targetObject){
ActiveLockOnTarget thisTarget = activeTargets.Find(target => target.gameObject == targetObject);
yield return new WaitForEndOfFrame();
while (activeTargets.Contains(thisTarget)) {
yield return null;
}
Destroy(thisTarget.gameObject);
}
public void ChangeLockOnTarget(){
Transform cameraTransform = Camera.main.transform;
@@ -203,7 +229,8 @@ public class LockOnManager : MonoBehaviour{
AddNewTarget(closestTarget.gameObject, mainTargetWeight, true);
}
public void RemoveLockOnTarget(){
// Used by outside sources such as input to cancel lock-on.
public void RemoveMainTarget(){
QueueTargetRemoval(mainTarget.gameObject);
}

View File

@@ -11,7 +11,7 @@ public struct CameraSettingSingleValue<T>{
public Vector2 velocityRefV2;
public Vector3 velocityRefV3;
public CameraSettingSingleValue(float defaultSmoothing, T original = default(T)){
public CameraSettingSingleValue(float defaultSmoothing = .2f, T original = default(T)){
originalValue = original;
targetValue = original;
smoothing = defaultSmoothing;
@@ -106,11 +106,12 @@ public class CameraSettingsProcessor : MonoBehaviour{
values = new CameraSettingValues{
cameraOffsetOffset = new CameraSettingSingleValue<Vector3>(defaultSmoothing: .2f, offset.Offset),
mainFieldOfView = new CameraSettingSingleValue<float>(defaultSmoothing: .2f, main.Lens.FieldOfView),
axisLookEnabledX = new CameraSettingSingleValue<bool>(0f, axisCont.Controllers[0].Enabled),
axisLookEnabledY = new CameraSettingSingleValue<bool>(0f, axisCont.Controllers[1].Enabled),
axisLookEnabledX = new CameraSettingSingleValue<bool>(0, axisCont.Controllers[0].Enabled),
axisLookEnabledY = new CameraSettingSingleValue<bool>(0, axisCont.Controllers[1].Enabled),
axisLookGainX = new CameraSettingSingleValue<float>(defaultSmoothing: .2f, axisCont.Controllers[0].Input.Gain),
axisLookGainY = new CameraSettingSingleValue<float>(defaultSmoothing: .2f, axisCont.Controllers[1].Input.Gain),
orbitPositionDamping = new CameraSettingSingleValue<Vector3>(defaultSmoothing: .2f, orbit.TrackerSettings.PositionDamping),
orbitTargetOffset = new CameraSettingSingleValue<Vector3>(defaultSmoothing: .1f, orbit.TargetOffset),
orbitFollowTopHeight = new CameraSettingSingleValue<float>(defaultSmoothing: .2f, orbit.Orbits.Top.Height),
orbitFollowTopRadius = new CameraSettingSingleValue<float>(defaultSmoothing: .2f, orbit.Orbits.Top.Radius),
orbitFollowCenterHeight = new CameraSettingSingleValue<float>(defaultSmoothing: .2f, orbit.Orbits.Center.Height),

View File

@@ -6,14 +6,44 @@ public interface ILockOnTarget {
Transform transform {get;}
GameObject gameObject{ get; }
abstract void OnTargetDelete();
void Help(){
SafelyDeleteTarget();
}
public Vector3 GetReticlePosition(){
Bounds objectBounds = gameObject.GetComponent<Renderer>().bounds;
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 + objectBounds.size.y, transform.position.z);
Vector3 reticlePosition = new Vector3(transform.position.x, transform.position.y + upValue, transform.position.z);
return reticlePosition;
}
public void OnEnable(){
Debug.Log("hewwo");
}
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}};
Debug.Log("hii");
target.gameObject = clone;
target.cinemachineTarget.Object = clone.transform;
LockOnManager.Instance.QueueTargetRemoval(clone, true);
}
}
}
}
public class PlayerCamera : MonoBehaviour{

View File

@@ -76,7 +76,7 @@ public class PlayerControls : MonoBehaviour{
}
public void OnCancelLockOn(){
GetComponent<LockOnManager>().RemoveLockOnTarget();
GetComponent<LockOnManager>().RemoveMainTarget();
graph.SendEvent<string>("InputEvent", "CancelLockOn", null);
}