playMaker

Author Topic: Add max Degrees to SmoothLookAt function  (Read 2511 times)

Stuard

  • Playmaker Newbie
  • *
  • Posts: 15
Add max Degrees to SmoothLookAt function
« on: July 28, 2017, 07:21:27 PM »
Hello guys,
i cant get it to work right... first try with default values and a target worked but unity crashed shortly after i changed to custom values in speed and maxdegrees.
Also my camara setup jitters after i modified this function and now i dont realy know what to do ;D

Code: [Select]
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

// (c) Copyright HutongGames, LLC 2010-2013. All rights reserved.

namespace HutongGames.PlayMaker.Actions
{
[ActionCategory(ActionCategory.Transform)]
[Tooltip("Smoothly Rotates a Game Object so its forward vector points at a Target. The target can be defined as a Game Object or a world Position. If you specify both, then the position will be used as a local offset from the object's position.")]
public class SmoothLookAtMaximumDegrees : FsmStateAction
{
[RequiredField]
[Tooltip("The GameObject to rotate to face a target.")]
public FsmOwnerDefault gameObject;

[Tooltip("A target GameObject.")]
public FsmGameObject targetObject;

[Tooltip("A target position. If a Target Object is defined, this is used as a local offset.")]
public FsmVector3 targetPosition;

[Tooltip("Used to keep the game object generally upright. If left undefined the world y axis is used.")]
public FsmVector3 upVector;

[Tooltip("Force the game object to remain vertical. Useful for characters.")]
public FsmBool keepVertical;

[HasFloatSlider(0.5f,15)]
[Tooltip("How fast the look at moves.")]
public FsmFloat speed;

[Tooltip("Maximum amount of rotation per second.")]
public FsmFloat MaxDegrees;

[Tooltip("Draw a line in the Scene View to the look at position.")]
public FsmBool debug;

[Tooltip("If the angle to the target is less than this, send the Finish Event below. Measured in degrees.")]
public FsmFloat finishTolerance;

[Tooltip("Event to send if the angle to target is less than the Finish Tolerance.")]
public FsmEvent finishEvent;

private GameObject previousGo; // track game object so we can re-initialize when it changes.
private Quaternion lastRotation;
private Quaternion desiredRotation;

public override void Reset()
{
gameObject = null;
targetObject = null;
targetPosition = new FsmVector3 { UseVariable = true};
upVector = new FsmVector3 { UseVariable = true};
keepVertical = true;
debug = false;
speed = 5;
MaxDegrees = 5;
finishTolerance = 1;
finishEvent = null;
}

public override void OnEnter()
{
previousGo = null;
}

public override void OnLateUpdate()
{
DoSmoothLookAt();
}

void DoSmoothLookAt()
{
var go = Fsm.GetOwnerDefaultTarget(gameObject);
if (go == null)
{
return;
}

var goTarget = targetObject.Value;
if (goTarget == null && targetPosition.IsNone)
{
return;
}

// re-initialize if game object has changed

if (previousGo != go)
{
lastRotation = go.transform.rotation;
desiredRotation = lastRotation;
previousGo = go;
}

// desired look at position

Vector3 lookAtPos;
if (goTarget != null)
{
lookAtPos = !targetPosition.IsNone ?
goTarget.transform.TransformPoint(targetPosition.Value) :
goTarget.transform.position;
}
else
{
lookAtPos = targetPosition.Value;
}

if (keepVertical.Value)
{
lookAtPos.y = go.transform.position.y;
}

// smooth look at

var diff = lookAtPos - go.transform.position;
if (diff != Vector3.zero && diff.sqrMagnitude > 0)
{
desiredRotation = Quaternion.LookRotation(diff, upVector.IsNone ? Vector3.up : upVector.Value); //Where i modified the script
}

Quaternion diffq = Quaternion.Euler(diff);

lastRotation = Quaternion.Slerp(desiredRotation, diffq, Time.deltaTime * speed.Value);

float angle = Quaternion.Angle (desiredRotation, lastRotation);
float MaxAngle = MaxDegrees.Value * Time.deltaTime;
if (angle > MaxAngle) {
lastRotation = Quaternion.Slerp (lastRotation, desiredRotation, MaxAngle / angle);
}

go.transform.rotation = lastRotation;

// debug line to target

if (debug.Value)
{
Debug.DrawLine(go.transform.position, lookAtPos, Color.grey);
}

// send finish event?

if (finishEvent != null)
{
var targetDir = lookAtPos - go.transform.position;
var angleCalc = Vector3.Angle(targetDir, go.transform.forward);

if (Mathf.Abs(angleCalc) <= finishTolerance.Value)
{
Fsm.Event(finishEvent);
}
}
}

}
}

and the Lines i modified;

Code: [Select]
var diff = lookAtPos - go.transform.position;
if (diff != Vector3.zero && diff.sqrMagnitude > 0)
{
desiredRotation = Quaternion.LookRotation(diff, upVector.IsNone ? Vector3.up : upVector.Value); //Where i modified the script
}

Quaternion diffq = Quaternion.Euler(diff);

lastRotation = Quaternion.Slerp(desiredRotation, diffq, Time.deltaTime * speed.Value);

float angle = Quaternion.Angle (desiredRotation, lastRotation);
float MaxAngle = MaxDegrees.Value * Time.deltaTime;
if (angle > MaxAngle) {
lastRotation = Quaternion.Slerp (lastRotation, desiredRotation, MaxAngle / angle);
}

go.transform.rotation = lastRotation;


And the stuff that happens ingame :I
https://www.dropbox.com/s/j4esaw1f7m6x4jl/screen.gif?dl=0

Stuard

  • Playmaker Newbie
  • *
  • Posts: 15
Re: Add max Degrees to SmoothLookAt function
« Reply #1 on: July 29, 2017, 08:35:57 AM »
hello,
i realized that i need another quaternion to save the rotation and then calculate the degree cap but well unity crashed again :I

Code: [Select]
var diff = lookAtPos - go.transform.position;
if (diff != Vector3.zero && diff.sqrMagnitude > 0)
{
desiredRotation = Quaternion.LookRotation(diff, upVector.IsNone ? Vector3.up : upVector.Value);
}

currentRotation = Quaternion.Slerp(lastRotation, desiredRotation, speed.Value * Time.deltaTime); //crash here so i guesss its m calculation below

float angle = Quaternion.Angle (lastRotation, currentRotation);
float MaxAngle = MaxDegrees.Value * Time.deltaTime;
if (angle > MaxAngle) {
currentRotation = Quaternion.Slerp (lastRotation, currentRotation, MaxAngle / angle);
}


go.transform.rotation = currentRotation;

Stuard

  • Playmaker Newbie
  • *
  • Posts: 15
Re: Add max Degrees to SmoothLookAt function
« Reply #2 on: July 30, 2017, 05:46:18 AM »
Hello,
i mean, what am i doing wrong? I just grab the currentRotation of the existing code and just check if its faster than whats standard.. 5 degrees per second and cap it that it cant go faster than that  :-\

TurretRotation > 10 d/s check
goes faster cap it and return it to a constand value until its slower :o

djaydino

  • Administrator
  • Hero Member
  • *****
  • Posts: 7616
    • jinxtergames
Re: Add max Degrees to SmoothLookAt function
« Reply #3 on: July 30, 2017, 05:49:44 AM »
Hi,
Maybe you can use the 'Torque Look Rotation' action on the Ecosystem

or look into that script.


Stuard

  • Playmaker Newbie
  • *
  • Posts: 15
Re: Add max Degrees to SmoothLookAt function
« Reply #4 on: July 31, 2017, 03:29:28 AM »
Thanks for your reply, i will look into that :)

Stuard

  • Playmaker Newbie
  • *
  • Posts: 15
Re: Add max Degrees to SmoothLookAt function
« Reply #5 on: August 02, 2017, 07:55:18 AM »
hey djaydino,
thanks for your reply but i guess i have to find another way since my limeted understandment prevents me finding my error but thank you nontheless :)

Actually im trying to rebuild the script from this thread https://forum.unity3d.com/threads/gradual-rotation-change.60793/ *last post*. The reason is that it is "imprecisely" becaus it even with lateUpdate jitters my camara setup. And the SmoothLookAt function was realy smooth so i thought adding that feature must be easy but i isn't and i havent realy understand the difference between quaternions and Vector3's ;D

Can i rebuild that script in states? I looked into it and got some movement working but not in a way i want it  :o