您最多选择25个主题
主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
142 行
5.1 KiB
142 行
5.1 KiB
using System;
|
|
using Unity.Collections;
|
|
using UnityEngine;
|
|
using UnityEngine.Experimental.Animations;
|
|
|
|
public struct AimDragJob : IAnimationJob
|
|
{
|
|
[Serializable]
|
|
public struct Settings
|
|
{
|
|
[Range(0.0f, 10f)]
|
|
public float stiffness;
|
|
[Range(0.0f, 180f)]
|
|
public float maxAngle;
|
|
[Range(-1.0f, 1.0f)]
|
|
public float dragWeight;
|
|
[Range(-1.0f, 1.0f)]
|
|
public float rollWeight;
|
|
[Range(0, 10)]
|
|
public int rollDelay;
|
|
public Vector3 dragPivot;
|
|
public Vector3 rollPivot;
|
|
}
|
|
|
|
[Serializable]
|
|
public struct EditorSettings
|
|
{
|
|
// The non job reference types
|
|
public Transform weaponHandBone;
|
|
public Transform weaponBone;
|
|
public Transform applyResultOn;
|
|
|
|
// All the value types
|
|
public Settings settings;
|
|
|
|
public bool HasValidData()
|
|
{
|
|
return weaponHandBone != null & weaponBone != null & applyResultOn != null;
|
|
}
|
|
}
|
|
|
|
TransformStreamHandle m_Effectorhandle;
|
|
TransformStreamHandle m_WeaponPivot;
|
|
TransformSceneHandle m_WeaponHandResult;
|
|
|
|
bool m_AimDirectionInitialized;
|
|
NativeQueue<Quaternion> m_DragHistory;
|
|
float m_CurrentYaw;
|
|
float m_CurrentPitch;
|
|
|
|
public Settings settings;
|
|
public CharAnimState animState;
|
|
|
|
public bool Setup(Animator animator, EditorSettings editorSettings, float deltaTime, NativeQueue<Quaternion> dragHistory)
|
|
{
|
|
if (!editorSettings.HasValidData())
|
|
{
|
|
return false;
|
|
}
|
|
|
|
settings = editorSettings.settings;
|
|
m_Effectorhandle = animator.BindStreamTransform(editorSettings.weaponHandBone);
|
|
m_WeaponPivot = animator.BindStreamTransform(editorSettings.weaponBone);
|
|
m_WeaponHandResult = animator.BindSceneTransform(editorSettings.applyResultOn);
|
|
m_DragHistory = dragHistory;
|
|
return true;
|
|
}
|
|
|
|
public void Update(Vector3 target, Settings settings, CharAnimState animationState, AnimationScriptPlayable playable)
|
|
{
|
|
var job = playable.GetJobData<AimDragJob>();
|
|
job.settings = settings;
|
|
job.animState = animationState;
|
|
playable.SetJobData(job);
|
|
}
|
|
|
|
|
|
public void ProcessRootMotion(AnimationStream stream) { }
|
|
|
|
public void ProcessAnimation(AnimationStream stream)
|
|
{
|
|
if (!m_AimDirectionInitialized)
|
|
{
|
|
m_CurrentYaw = animState.aimYaw;
|
|
m_CurrentPitch = animState.aimPitch;
|
|
m_AimDirectionInitialized = true;
|
|
}
|
|
|
|
// TODO: (sunek) Get rid of stuttering
|
|
var t = settings.stiffness * stream.deltaTime;
|
|
m_CurrentYaw = Mathf.LerpAngle(m_CurrentYaw, animState.aimYaw, t);
|
|
m_CurrentPitch = Mathf.LerpAngle(m_CurrentPitch, animState.aimPitch, t);
|
|
|
|
var deltaYaw = Mathf.DeltaAngle(animState.aimYaw, m_CurrentYaw);
|
|
var deltaPitch = Mathf.DeltaAngle(animState.aimPitch, m_CurrentPitch);
|
|
var deltaRotation = Quaternion.Euler(new Vector3(-deltaPitch, deltaYaw, 0));
|
|
|
|
var angle = Quaternion.Angle(Quaternion.identity, deltaRotation);
|
|
if (angle > settings.maxAngle)
|
|
{
|
|
t = settings.maxAngle / angle;
|
|
m_CurrentYaw = Mathf.LerpAngle(animState.aimYaw, m_CurrentYaw, t);
|
|
m_CurrentPitch = Mathf.LerpAngle(animState.aimPitch, m_CurrentPitch, t);
|
|
|
|
deltaYaw = Mathf.DeltaAngle(animState.aimYaw, m_CurrentYaw);
|
|
deltaPitch = Mathf.DeltaAngle(animState.aimPitch, m_CurrentPitch);
|
|
deltaRotation = Quaternion.Euler(new Vector3(-deltaPitch, deltaYaw, 0));
|
|
}
|
|
|
|
if (m_DragHistory.Count <= settings.rollDelay)
|
|
{
|
|
m_DragHistory.Enqueue(deltaRotation);
|
|
}
|
|
|
|
var drag = Quaternion.SlerpUnclamped(Quaternion.identity, deltaRotation, settings.dragWeight);
|
|
var roll = m_DragHistory.Count < settings.rollDelay + 1 ? m_DragHistory.Peek() : m_DragHistory.Dequeue();
|
|
roll = Quaternion.SlerpUnclamped(Quaternion.identity, new Quaternion(0f, roll.y, 0f, roll.w), settings.rollWeight);
|
|
|
|
var handPosition = m_Effectorhandle.GetPosition(stream);
|
|
var handRotation = m_Effectorhandle.GetRotation(stream);
|
|
var weaponPivotPosition = m_WeaponPivot.GetPosition(stream);
|
|
var weaponPivotRotation = m_WeaponPivot.GetRotation(stream);
|
|
|
|
var dragPivot = weaponPivotRotation * settings.dragPivot;
|
|
var rollPivot = weaponPivotRotation * settings.rollPivot;
|
|
|
|
var dragPivotDelta = handPosition - (weaponPivotPosition + dragPivot);
|
|
var rollPivotDelta = handPosition - (weaponPivotPosition + rollPivot);
|
|
|
|
var handOffset = drag * dragPivotDelta;
|
|
handOffset = handOffset - dragPivotDelta;
|
|
|
|
var rollOffset = roll * rollPivotDelta;
|
|
rollOffset = rollOffset - rollPivotDelta;
|
|
|
|
handPosition = handPosition + handOffset + rollOffset;
|
|
handRotation = drag * handRotation * roll;
|
|
|
|
m_WeaponHandResult.SetPosition(stream, handPosition);
|
|
m_WeaponHandResult.SetRotation(stream, handRotation);
|
|
}
|
|
}
|