feat(scene-mgmt): 添加角色立绘持续振动指令

This commit is contained in:
2026-07-19 20:31:16 +08:00
parent 7fa12e3d46
commit ba19c2eff5
2 changed files with 79 additions and 0 deletions
@@ -21,6 +21,9 @@ namespace AibisDream
protected float _alpha;
protected SpriteRenderer spriteRenderer;
private Tween _shakeTween;
private Vector3 _shakeOrigin;
public string ActorName => _actorName;
public string SlotName => _slotName;
public ActorType ActorType => _actorType;
@@ -96,6 +99,7 @@ namespace AibisDream
public void SetSlot(ActorSlot slot)
{
StopShake();
transform.position = slot.Position;
spriteRenderer.sortingOrder = slot.sortingOrder;
spriteRenderer.sortingLayerID = slot.sortingLayer;
@@ -103,6 +107,52 @@ namespace AibisDream
_slotName = slot.slotName;
}
/// <summary>
/// 持续振动角色立绘;再次调用会用新参数替换当前振动。
/// </summary>
public void StartShake(float strength, float cycleDuration, int vibrato)
{
StopShake();
strength = Mathf.Max(0.001f, strength);
cycleDuration = Mathf.Max(0.05f, cycleDuration);
vibrato = Mathf.Max(1, vibrato);
_shakeOrigin = transform.position;
_shakeTween = transform
.DOShakePosition(
cycleDuration,
new Vector3(strength, strength * 0.35f, 0f),
vibrato,
90f,
false,
false,
ShakeRandomnessMode.Full)
.SetEase(Ease.Linear)
.SetLoops(-1, LoopType.Restart)
.SetLink(gameObject, LinkBehaviour.KillOnDestroy);
}
/// <summary>
/// 停止振动,并将立绘恢复到开始振动前的位置。
/// </summary>
public void StopShake()
{
if (_shakeTween == null)
{
return;
}
_shakeTween.Kill();
_shakeTween = null;
transform.position = _shakeOrigin;
}
protected virtual void OnDestroy()
{
StopShake();
}
public IEnumerator FadeInAsync(float duration)
{
_alpha = 1;
@@ -245,5 +245,34 @@ namespace AibisDream
actor.SetFaceState(faceName);
}
}
/// <summary>
/// 持续振动角色立绘。默认作用于诊室槽位,强度单位为世界坐标。
/// 用法:&lt;&lt;start_actor_shake&gt;&gt; 或 &lt;&lt;start_actor_shake 火山 0.04 0.25 18&gt;&gt;
/// </summary>
[YarnCommand("start_actor_shake")]
public static void StartActorShake(
string actorName = ClinicSlotName,
float strength = 0.04f,
float cycleDuration = 0.25f,
int vibrato = 18)
{
if (ActorManager.Instance.TryFindActor(actorName, out var actor))
{
actor.StartShake(strength, cycleDuration, vibrato);
}
}
/// <summary>
/// 停止角色立绘振动并复位。默认作用于诊室槽位。
/// </summary>
[YarnCommand("stop_actor_shake")]
public static void StopActorShake(string actorName = ClinicSlotName)
{
if (ActorManager.Instance.TryFindActor(actorName, out var actor))
{
actor.StopShake();
}
}
}
}