1
This commit is contained in:
@@ -16665,9 +16665,10 @@ Transform:
|
|||||||
m_PrefabAsset: {fileID: 0}
|
m_PrefabAsset: {fileID: 0}
|
||||||
m_GameObject: {fileID: 740063969509039210}
|
m_GameObject: {fileID: 740063969509039210}
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
||||||
m_LocalRotation: {x: 0.022178197, y: -0.8962363, z: -0.44072056, w: -0.045100927}
|
m_LocalRotation: {x: -0.00000008975619, y: -0.0000000037252894, z: -0.000000009313224,
|
||||||
m_LocalPosition: {x: -1.6, y: -651, z: 367.017}
|
w: 1}
|
||||||
m_LocalScale: {x: 4, y: 4, z: 4}
|
m_LocalPosition: {x: 0.00065787137, y: -2.2404072, z: 0.00038540363}
|
||||||
|
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||||
m_ConstrainProportionsScale: 0
|
m_ConstrainProportionsScale: 0
|
||||||
m_Children:
|
m_Children:
|
||||||
- {fileID: 3481679758668778176}
|
- {fileID: 3481679758668778176}
|
||||||
@@ -16678,7 +16679,7 @@ Transform:
|
|||||||
- {fileID: 6933049547833441108}
|
- {fileID: 6933049547833441108}
|
||||||
- {fileID: 435495233371252481}
|
- {fileID: 435495233371252481}
|
||||||
- {fileID: 332384575434902884}
|
- {fileID: 332384575434902884}
|
||||||
m_Father: {fileID: 5300665937812909477}
|
m_Father: {fileID: 3915867836316660558}
|
||||||
m_LocalEulerAnglesHint: {x: 127.62907, y: -5.7616835, z: -180}
|
m_LocalEulerAnglesHint: {x: 127.62907, y: -5.7616835, z: -180}
|
||||||
--- !u!95 &9207702130346328658
|
--- !u!95 &9207702130346328658
|
||||||
Animator:
|
Animator:
|
||||||
@@ -129809,7 +129810,6 @@ Transform:
|
|||||||
- {fileID: 7568336788011164913}
|
- {fileID: 7568336788011164913}
|
||||||
- {fileID: 3542255443495026422}
|
- {fileID: 3542255443495026422}
|
||||||
- {fileID: 1107679922137602769}
|
- {fileID: 1107679922137602769}
|
||||||
- {fileID: 7938343961355029771}
|
|
||||||
m_Father: {fileID: 8132092681826129082}
|
m_Father: {fileID: 8132092681826129082}
|
||||||
m_LocalEulerAnglesHint: {x: -98.42819, y: -26.024849, z: 4.9341335}
|
m_LocalEulerAnglesHint: {x: -98.42819, y: -26.024849, z: 4.9341335}
|
||||||
--- !u!1 &4585606832032713547
|
--- !u!1 &4585606832032713547
|
||||||
@@ -129844,6 +129844,39 @@ Transform:
|
|||||||
- {fileID: 7263323558999938589}
|
- {fileID: 7263323558999938589}
|
||||||
m_Father: {fileID: 3071025295658667923}
|
m_Father: {fileID: 3071025295658667923}
|
||||||
m_LocalEulerAnglesHint: {x: 1.9001371, y: 16.84119, z: 23.392797}
|
m_LocalEulerAnglesHint: {x: 1.9001371, y: 16.84119, z: 23.392797}
|
||||||
|
--- !u!1 &4613593476530511081
|
||||||
|
GameObject:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
serializedVersion: 6
|
||||||
|
m_Component:
|
||||||
|
- component: {fileID: 3915867836316660558}
|
||||||
|
m_Layer: 21
|
||||||
|
m_Name: 4013@skin (1)
|
||||||
|
m_TagString: Untagged
|
||||||
|
m_Icon: {fileID: 0}
|
||||||
|
m_NavMeshLayer: 0
|
||||||
|
m_StaticEditorFlags: 0
|
||||||
|
m_IsActive: 1
|
||||||
|
--- !u!4 &3915867836316660558
|
||||||
|
Transform:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 4613593476530511081}
|
||||||
|
serializedVersion: 2
|
||||||
|
m_LocalRotation: {x: 0.022178197, y: -0.8962363, z: -0.44072056, w: -0.045100927}
|
||||||
|
m_LocalPosition: {x: -2.26, y: -645.9, z: 373.6}
|
||||||
|
m_LocalScale: {x: 4, y: 4, z: 4}
|
||||||
|
m_ConstrainProportionsScale: 0
|
||||||
|
m_Children:
|
||||||
|
- {fileID: 8132092681826129082}
|
||||||
|
- {fileID: 7938343961355029771}
|
||||||
|
m_Father: {fileID: 5300665937812909477}
|
||||||
|
m_LocalEulerAnglesHint: {x: 127.62907, y: -5.7616835, z: -180}
|
||||||
--- !u!1 &4726541080467135181
|
--- !u!1 &4726541080467135181
|
||||||
GameObject:
|
GameObject:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
@@ -151701,13 +151734,13 @@ Transform:
|
|||||||
m_PrefabAsset: {fileID: 0}
|
m_PrefabAsset: {fileID: 0}
|
||||||
m_GameObject: {fileID: 6075757578092001718}
|
m_GameObject: {fileID: 6075757578092001718}
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
||||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
m_LocalRotation: {x: -0.36096528, y: 0.587986, z: 0.6076233, w: 0.39340886}
|
||||||
m_LocalPosition: {x: 0.18, y: 0, z: 0.28}
|
m_LocalPosition: {x: -0.06, y: 0.02, z: -0.03}
|
||||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||||
m_ConstrainProportionsScale: 0
|
m_ConstrainProportionsScale: 0
|
||||||
m_Children:
|
m_Children:
|
||||||
- {fileID: 2472551500261950760}
|
- {fileID: 2472551500261950760}
|
||||||
m_Father: {fileID: 8689155732104790751}
|
m_Father: {fileID: 3915867836316660558}
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: -0, z: -0}
|
m_LocalEulerAnglesHint: {x: 0, y: -0, z: -0}
|
||||||
--- !u!198 &5623801317964350462
|
--- !u!198 &5623801317964350462
|
||||||
ParticleSystem:
|
ParticleSystem:
|
||||||
@@ -185145,7 +185178,7 @@ Transform:
|
|||||||
m_PrefabAsset: {fileID: 0}
|
m_PrefabAsset: {fileID: 0}
|
||||||
m_GameObject: {fileID: 7018613850427909376}
|
m_GameObject: {fileID: 7018613850427909376}
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
||||||
m_LocalRotation: {x: 0.07106404, y: 0.7890955, z: 0.60262835, w: 0.09548442}
|
m_LocalRotation: {x: 0.07106401, y: 0.7890956, z: 0.6026283, w: 0.095484376}
|
||||||
m_LocalPosition: {x: -1.2034149, y: -4.150479, z: 3.3754418}
|
m_LocalPosition: {x: -1.2034149, y: -4.150479, z: 3.3754418}
|
||||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||||
m_ConstrainProportionsScale: 0
|
m_ConstrainProportionsScale: 0
|
||||||
@@ -211511,7 +211544,7 @@ Transform:
|
|||||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||||
m_ConstrainProportionsScale: 0
|
m_ConstrainProportionsScale: 0
|
||||||
m_Children:
|
m_Children:
|
||||||
- {fileID: 8132092681826129082}
|
- {fileID: 3915867836316660558}
|
||||||
- {fileID: 4993782737479821777}
|
- {fileID: 4993782737479821777}
|
||||||
- {fileID: 2430006080572331403}
|
- {fileID: 2430006080572331403}
|
||||||
- {fileID: 2196620004794829531}
|
- {fileID: 2196620004794829531}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -3,7 +3,7 @@ using System.Collections.Generic;
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.InputSystem; // Pointer.current:鼠标拖动 / 屏幕滑动统一采样
|
using UnityEngine.InputSystem; // Pointer.current:鼠标拖动 / 屏幕滑动统一采样
|
||||||
|
|
||||||
/// <summary>战神跟手旋转的旋转轴(3D 模型按轴转身,各战神模型朝向不同,面板可选)</summary>
|
/// <summary>战神跟手旋转的旋转轴(世界坐标 X/Y/Z,绕世界轴转不受父节点朝向影响)</summary>
|
||||||
public enum ZhanShenRotateAxis
|
public enum ZhanShenRotateAxis
|
||||||
{
|
{
|
||||||
X = 0,
|
X = 0,
|
||||||
@@ -33,9 +33,9 @@ public class ZhanShenTurretData : TurretData
|
|||||||
[Tooltip("战神普通开火音效(未锁定时):不锁定开炮时逐发播放;为空则回退普通炮台音效 bulletClip")]
|
[Tooltip("战神普通开火音效(未锁定时):不锁定开炮时逐发播放;为空则回退普通炮台音效 bulletClip")]
|
||||||
public AudioClip bulletAudio;
|
public AudioClip bulletAudio;
|
||||||
|
|
||||||
[Tooltip("旋转目标对象:跟手旋转时被旋转的节点(只转它 rotateAxis 那一个轴,其他轴和位移都不动)。为空回退战神实例自身")]
|
[Tooltip("旋转目标对象:跟手旋转时被旋转的节点(按世界轴旋转,其它轴和位移都不动)。为空回退战神实例自身")]
|
||||||
public Transform rotateTargetNode;
|
public Transform rotateTargetNode;
|
||||||
[Tooltip("跟手旋转绕哪个轴:3D 模型转身一般是 Y,部分模型/特效用 X 或 Z")]
|
[Tooltip("跟手旋转绕哪个【世界坐标】轴:Y=竖直轴转身(默认),X/Z 同理。用世界轴不受父节点朝向和本地姿态影响")]
|
||||||
public ZhanShenRotateAxis rotateAxis = ZhanShenRotateAxis.Y;
|
public ZhanShenRotateAxis rotateAxis = ZhanShenRotateAxis.Y;
|
||||||
[Tooltip("跟手灵敏度:指针每滑动 1 像素累积多少度旋转。正数=向右划模型向右转、向左划向左转;想反方向就填负数")]
|
[Tooltip("跟手灵敏度:指针每滑动 1 像素累积多少度旋转。正数=向右划模型向右转、向左划向左转;想反方向就填负数")]
|
||||||
public float rotateSensitivity = 0.4f;
|
public float rotateSensitivity = 0.4f;
|
||||||
@@ -49,17 +49,17 @@ public class ZhanShenTurretData : TurretData
|
|||||||
/// <summary>是否正在跟手旋转(由 Timeline 事件 RotateZhanShen 开始、StopRotateZhanShen 结束)</summary>
|
/// <summary>是否正在跟手旋转(由 Timeline 事件 RotateZhanShen 开始、StopRotateZhanShen 结束)</summary>
|
||||||
private bool _rotateFollowing;
|
private bool _rotateFollowing;
|
||||||
private Coroutine _rotateRoutine;
|
private Coroutine _rotateRoutine;
|
||||||
/// <summary>累积的目标角度(原始值,可超过 360°,保证连续拖动不绕圈回跳)</summary>
|
/// <summary>累积的目标角度(增量,可超过 360°,保证连续拖动不绕圈回跳)</summary>
|
||||||
private float _rotateTargetAngle;
|
private float _rotateTargetAngle;
|
||||||
/// <summary>平滑显示用的角度(原始值,与 _rotateTargetAngle 同坐标系)</summary>
|
/// <summary>平滑显示用的角度(相对基准的增量,与 _rotateTargetAngle 同坐标系)</summary>
|
||||||
private float _rotateShownAngle;
|
private float _rotateShownAngle;
|
||||||
/// <summary>上一帧指针位置:按帧间位移量累加角度,所以按下时也要先把位置记准</summary>
|
/// <summary>已经真正叠加到节点上的角度:每帧只补"还差多少",不直接覆盖节点的旋转</summary>
|
||||||
private Vector2 _rotateLastPointerPos;
|
private float _rotateAppliedAngle;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ⭐ 旋转战神(Timeline 事件调用="开始点"):开始持续跟手旋转。
|
/// ⭐ 旋转战神(Timeline 事件调用="开始点"):开始持续跟手旋转。
|
||||||
/// 调用后每帧按指针(鼠标点击拖动 / 屏幕滑动)的横向位移量累加到目标角度,
|
/// 调用后每帧按指针(鼠标点击拖动 / 屏幕滑动)的横向位移量累加到目标角度,
|
||||||
/// 节点再按 rotateLerpSpeed 平滑绕 rotateAxis 转到该角度;累加从节点当前角度起步,不会跳变。
|
/// 节点再按 rotateLerpSpeed 平滑绕【世界坐标】rotateAxis 轴旋转到该角度。
|
||||||
/// 重复触发(Timeline 上多个事件)不会叠加协程。
|
/// 重复触发(Timeline 上多个事件)不会叠加协程。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void RotateZhanShen()
|
public void RotateZhanShen()
|
||||||
@@ -73,9 +73,10 @@ public class ZhanShenTurretData : TurretData
|
|||||||
if (node == null) return;
|
if (node == null) return;
|
||||||
|
|
||||||
_rotateFollowing = true;
|
_rotateFollowing = true;
|
||||||
_rotateTargetAngle = ReadAxisAngle(node.localEulerAngles); // 从当前角度开始累加
|
// 增量从 0 起算:不缓存任何"基准朝向/基准位置",每帧只在节点当前旋转上补差值 → 起步不跳、松手不回弹
|
||||||
_rotateShownAngle = _rotateTargetAngle;
|
_rotateTargetAngle = 0f;
|
||||||
_rotateLastPointerPos = ReadPointerPos();
|
_rotateShownAngle = 0f;
|
||||||
|
_rotateAppliedAngle = 0f;
|
||||||
_rotateRoutine = StartCoroutine(FollowRotateRoutine());
|
_rotateRoutine = StartCoroutine(FollowRotateRoutine());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,44 +100,82 @@ public class ZhanShenTurretData : TurretData
|
|||||||
var node = ResolveRotateTargetNode();
|
var node = ResolveRotateTargetNode();
|
||||||
if (node == null) break;
|
if (node == null) break;
|
||||||
|
|
||||||
|
// ⭐ 只累加"本帧滑动距离",不记录、不比较任何指针位置:
|
||||||
|
// Pointer.delta 是输入系统给的本帧位移量(鼠标/触摸通用),按下就按位移累加,
|
||||||
|
// 松手 delta 自然为 0。没有"初始位置"这种东西,所以点一下(没滑动)一定不会转。
|
||||||
var pointer = Pointer.current;
|
var pointer = Pointer.current;
|
||||||
|
bool pressed = false;
|
||||||
|
float deltaX = 0f;
|
||||||
if (pointer != null)
|
if (pointer != null)
|
||||||
{
|
{
|
||||||
Vector2 cur = pointer.position.ReadValue();
|
pressed = pointer.press.isPressed;
|
||||||
// 按住(拖动中)才累加:松手保持当前角度
|
deltaX = pointer.delta.ReadValue().x;
|
||||||
// ⚠ 这里用 -= 而不是 +=:Unity 绕 Y 轴的正角度在屏幕上看是"向左转"(相机朝 -Z 看时
|
// ⚠ 这里用 -= 而不是 +=:Unity 绕 +Y 的正角度在屏幕上看是"向左转"(相机朝 -Z 看时
|
||||||
// +θ 把模型的正面转向 -X),所以"向右划=向右转"必须把右移量反号。改回 += 方向就会反。
|
// +θ 把模型的正面转向 -X),所以"向右划=向右转"必须把右移量反号。改回 += 方向就会反。
|
||||||
if (pointer.press.isPressed)
|
if (pressed)
|
||||||
_rotateTargetAngle -= (cur.x - _rotateLastPointerPos.x) * rotateSensitivity;
|
_rotateTargetAngle -= deltaX * rotateSensitivity;
|
||||||
// ⚠ 不管有没有按住都记录位置:否则按下那一帧会用"开始跟手时的旧位置"算出巨大跳变
|
|
||||||
_rotateLastPointerPos = cur;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_rotateShownAngle = rotateLerpSpeed > 0f
|
_rotateShownAngle = rotateLerpSpeed > 0f
|
||||||
? Mathf.Lerp(_rotateShownAngle, _rotateTargetAngle, Mathf.Clamp01(rotateLerpSpeed * Time.deltaTime))
|
? Mathf.Lerp(_rotateShownAngle, _rotateTargetAngle, Mathf.Clamp01(rotateLerpSpeed * Time.deltaTime))
|
||||||
: _rotateTargetAngle;
|
: _rotateTargetAngle;
|
||||||
|
|
||||||
// 只改 rotateAxis 那一个轴:其余两轴沿用节点当前值(模型只绕该轴转身)
|
// ⭐ 绕【世界坐标】轴旋转,但**增量式叠加**,绝不覆盖节点的朝向:
|
||||||
Vector3 e = node.localEulerAngles;
|
// ① 世界轴先换算到节点所在父级坐标系(axisLocal);父级跟着瞄准转时,这跟轴也跟着转,
|
||||||
switch (rotateAxis)
|
// 于是"绕世界竖直轴"在任何父级朝向下都成立;
|
||||||
|
// ② 把差值(本帧该补多少度)左乘在当前 localRotation 上 —— 节点本来什么姿态就叠在什么上面,
|
||||||
|
// 不缓存基准、不锁世界朝向,所以:点一下不滑动 = 差值 0 = 完全不动;
|
||||||
|
// 父级/动画改写了该节点的旋转也不会被顶回去(这就是上一版"点一下就转了个圈"的原因:
|
||||||
|
// 上一版直接写 node.rotation = AngleAxis(角度) × 缓存基准,把世界朝向锁死了)。
|
||||||
|
float step = _rotateShownAngle - _rotateAppliedAngle;
|
||||||
|
if (Mathf.Abs(step) > 1e-4f)
|
||||||
{
|
{
|
||||||
case ZhanShenRotateAxis.X: e.x = _rotateShownAngle; break;
|
Vector3 worldAxis = GetWorldAxis();
|
||||||
case ZhanShenRotateAxis.Z: e.z = _rotateShownAngle; break;
|
Vector3 axisLocal = node.parent != null
|
||||||
default: e.y = _rotateShownAngle; break;
|
? node.parent.InverseTransformDirection(worldAxis)
|
||||||
|
: worldAxis;
|
||||||
|
node.localRotation = Quaternion.AngleAxis(step, axisLocal) * node.localRotation;
|
||||||
|
_rotateAppliedAngle = _rotateShownAngle;
|
||||||
}
|
}
|
||||||
node.localEulerAngles = e;
|
|
||||||
|
#if UNITY_EDITOR
|
||||||
|
DebugRotateStep(node, pressed, deltaX, step);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
_rotateRoutine = null;
|
_rotateRoutine = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>取当前旋转轴上的角度(跟手累加的起点)</summary>
|
#if UNITY_EDITOR
|
||||||
private float ReadAxisAngle(Vector3 euler)
|
/// <summary>跟手旋转诊断计时(编辑器排查用,0.5 秒一条 + 大跳变立即报)</summary>
|
||||||
|
private float _rotateLogTimer = -99f;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 编辑器诊断:用它定死"转一圈"到底是不是本脚本干的。
|
||||||
|
/// 判读方法:
|
||||||
|
/// - 只点击没拖动时如果日志里 步进≈0、累计≈0,模型却自己转 → 不是这套代码,是 Timeline/Animator(或别的系统)在转;
|
||||||
|
/// - 如果日志出现很大的"步进"(几十~几百度)且时间点正好对齐你看到的转圈 → 才是这里算错了。
|
||||||
|
/// </summary>
|
||||||
|
private void DebugRotateStep(Transform node, bool pressed, float deltaX, float step)
|
||||||
|
{
|
||||||
|
_rotateLogTimer += Time.deltaTime;
|
||||||
|
bool bigJump = Mathf.Abs(step) > 5f;
|
||||||
|
if (_rotateLogTimer < 0.5f && !bigJump) return;
|
||||||
|
_rotateLogTimer = 0f;
|
||||||
|
|
||||||
|
Debug.Log($"[战神跟手旋转] 节点={node.name} 按住={pressed} 本帧滑动={deltaX:F1}px " +
|
||||||
|
$"本帧步进={step:F2}° 累计={_rotateShownAngle:F2}° 已叠加={_rotateAppliedAngle:F2}° " +
|
||||||
|
$"节点本地Euler={node.localEulerAngles} 节点世界Euler={node.eulerAngles}");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// <summary>面板选的轴转成世界坐标方向向量</summary>
|
||||||
|
private Vector3 GetWorldAxis()
|
||||||
{
|
{
|
||||||
switch (rotateAxis)
|
switch (rotateAxis)
|
||||||
{
|
{
|
||||||
case ZhanShenRotateAxis.X: return euler.x;
|
case ZhanShenRotateAxis.X: return Vector3.right;
|
||||||
case ZhanShenRotateAxis.Z: return euler.z;
|
case ZhanShenRotateAxis.Z: return Vector3.forward;
|
||||||
default: return euler.y;
|
default: return Vector3.up;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -145,12 +184,6 @@ public class ZhanShenTurretData : TurretData
|
|||||||
return rotateTargetNode != null ? rotateTargetNode : transform;
|
return rotateTargetNode != null ? rotateTargetNode : transform;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Vector2 ReadPointerPos()
|
|
||||||
{
|
|
||||||
var pointer = Pointer.current;
|
|
||||||
return pointer != null ? pointer.position.ReadValue() : Vector2.zero;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnDisable()
|
private void OnDisable()
|
||||||
{
|
{
|
||||||
// 战神实例被回收/隐藏时停止跟手,避免协程挂在已停用的对象上继续跑
|
// 战神实例被回收/隐藏时停止跟手,避免协程挂在已停用的对象上继续跑
|
||||||
|
|||||||
Reference in New Issue
Block a user