chore: initial commit
This commit is contained in:
0
Assets/Scripts/Feedback/.gitkeep
Normal file
0
Assets/Scripts/Feedback/.gitkeep
Normal file
18
Assets/Scripts/Feedback/BaseGames.Feedback.asmdef
Normal file
18
Assets/Scripts/Feedback/BaseGames.Feedback.asmdef
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"precompiledReferences": [],
|
||||
"name": "BaseGames.Feedback",
|
||||
"defineConstraints": [],
|
||||
"noEngineReferences": false,
|
||||
"versionDefines": [],
|
||||
"rootNamespace": "BaseGames.Feedback",
|
||||
"references": [
|
||||
"BaseGames.Core.Events",
|
||||
"BaseGames.Combat",
|
||||
"MoreMountains.Tools"
|
||||
],
|
||||
"autoReferenced": true,
|
||||
"overrideReferences": false,
|
||||
"includePlatforms": []
|
||||
}
|
||||
7
Assets/Scripts/Feedback/BaseGames.Feedback.asmdef.meta
Normal file
7
Assets/Scripts/Feedback/BaseGames.Feedback.asmdef.meta
Normal file
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4847ae647b0781e49b36458792d57902
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
20
Assets/Scripts/Feedback/FeedbackConfigSO.cs
Normal file
20
Assets/Scripts/Feedback/FeedbackConfigSO.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace BaseGames.Feedback
|
||||
{
|
||||
/// <summary>
|
||||
/// Feedback 系统全局配置:闪白颜色/时长等通用参数。
|
||||
/// 资产路径:Assets/ScriptableObjects/Feedback/FeedbackConfig.asset
|
||||
/// </summary>
|
||||
[CreateAssetMenu(menuName = "Feedback/FeedbackConfig")]
|
||||
public class FeedbackConfigSO : ScriptableObject
|
||||
{
|
||||
[Header("受伤闪白")]
|
||||
[Tooltip("Shader _FlashColor 参数目标颜色。")]
|
||||
public Color HurtFlashColor = Color.white;
|
||||
|
||||
[Tooltip("闪白持续时间(秒)。")]
|
||||
[Min(0.01f)]
|
||||
public float HurtFlashDuration = 0.12f;
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/Feedback/FeedbackConfigSO.cs.meta
Normal file
11
Assets/Scripts/Feedback/FeedbackConfigSO.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3a13bc45e10182c46a145c59e379bb30
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
68
Assets/Scripts/Feedback/IFeedbackPlayer.cs
Normal file
68
Assets/Scripts/Feedback/IFeedbackPlayer.cs
Normal file
@@ -0,0 +1,68 @@
|
||||
namespace BaseGames.Feedback
|
||||
{
|
||||
/// <summary>
|
||||
/// 反馈播放器接口:封装所有角色反馈行为,解耦 Character 逻辑与 Feel/MMF_Player 的直接依赖。
|
||||
/// 由 PlayerFeedback(玩家)和 EnemyFeedback(敌人)分别实现;
|
||||
/// NullFeedbackPlayer 用于测试/占位。
|
||||
/// </summary>
|
||||
public interface IFeedbackPlayer
|
||||
{
|
||||
// ── 命中 ──────────────────────────────────────────────────────────────────
|
||||
/// <summary>对目标造成命中时播放对应力度的反馈(摄像机震屏 + 控制器振动等)。</summary>
|
||||
void PlayHit(HitWeight weight);
|
||||
|
||||
/// <summary>成功弹反(Parry)时播放反馈。</summary>
|
||||
void PlayParrySuccess();
|
||||
|
||||
// ── 受伤 / 死亡 ──────────────────────────────────────────────────────────
|
||||
/// <summary>角色受到伤害时播放反馈(闪白 + 轻微震屏等)。</summary>
|
||||
void PlayTakeHit();
|
||||
|
||||
/// <summary>角色死亡时播放反馈(慢动作 + 震屏 + 音效)。</summary>
|
||||
void PlayDeath();
|
||||
|
||||
// ── 状态恢复 ─────────────────────────────────────────────────────────────
|
||||
/// <summary>治疗/恢复血量时播放反馈(粒子 + 音效)。</summary>
|
||||
void PlayHeal();
|
||||
|
||||
// ── 移动 / 动作 ──────────────────────────────────────────────────────────
|
||||
/// <summary>硬着陆时播放地面冲击反馈。</summary>
|
||||
void PlayLandImpact();
|
||||
|
||||
/// <summary>攻击出手时播放破风反馈。</summary>
|
||||
void PlayAttackWhoosh();
|
||||
|
||||
/// <summary>跳跃起跳时播放反馈。</summary>
|
||||
void PlayJumpLaunch();
|
||||
|
||||
// ── 通用 ─────────────────────────────────────────────────────────────────
|
||||
/// <summary>通过 presetId 触发在 Inspector 中配置的命名预设 MMF_Player。</summary>
|
||||
void TriggerPreset(string presetId);
|
||||
|
||||
/// <summary>通过 sfxId 触发单次音效(不带任何摄像机/振动反馈)。</summary>
|
||||
void PlaySFXById(string sfxId);
|
||||
}
|
||||
|
||||
/// <summary>命中力度。</summary>
|
||||
public enum HitWeight { Light, Medium, Heavy }
|
||||
|
||||
/// <summary>
|
||||
/// 空对象模式实现:所有方法均为空操作,用于测试和不需要反馈的实体。
|
||||
/// </summary>
|
||||
public class NullFeedbackPlayer : IFeedbackPlayer
|
||||
{
|
||||
public static readonly NullFeedbackPlayer Instance = new NullFeedbackPlayer();
|
||||
|
||||
public void PlayHit(HitWeight weight) { }
|
||||
public void PlayParrySuccess() { }
|
||||
public void PlayTakeHit() { }
|
||||
public void PlayDeath() { }
|
||||
public void PlayHeal() { }
|
||||
public void PlayLandImpact() { }
|
||||
public void PlayAttackWhoosh() { }
|
||||
public void PlayJumpLaunch() { }
|
||||
public void TriggerPreset(string presetId) { }
|
||||
public void PlaySFXById(string sfxId) { }
|
||||
}
|
||||
}
|
||||
|
||||
11
Assets/Scripts/Feedback/IFeedbackPlayer.cs.meta
Normal file
11
Assets/Scripts/Feedback/IFeedbackPlayer.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4baf6cd1a67e25347b18d8d8a13fbe02
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
104
Assets/Scripts/Feedback/PlayerFeedback.cs
Normal file
104
Assets/Scripts/Feedback/PlayerFeedback.cs
Normal file
@@ -0,0 +1,104 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using MoreMountains.Feedbacks;
|
||||
|
||||
namespace BaseGames.Feedback
|
||||
{
|
||||
/// <summary>
|
||||
/// 玩家反馈播放器:实现 IFeedbackPlayer,将行为语义映射到 MMF_Player 实例。
|
||||
/// 挂在玩家 GameObject 上(或子对象 [Feedback] 上)。
|
||||
/// 所有 MMF_Player 字段均在 Inspector 中配置 Feel 反馈链。
|
||||
/// </summary>
|
||||
public class PlayerFeedback : MonoBehaviour, IFeedbackPlayer
|
||||
{
|
||||
[Header("命中反馈")]
|
||||
[SerializeField] private MMF_Player _onHitLight;
|
||||
[SerializeField] private MMF_Player _onHitMedium;
|
||||
[SerializeField] private MMF_Player _onHitHeavy;
|
||||
[SerializeField] private MMF_Player _onParrySuccess;
|
||||
|
||||
[Header("受伤 / 死亡反馈")]
|
||||
[SerializeField] private MMF_Player _onTakeHit;
|
||||
[SerializeField] private MMF_Player _onDeath;
|
||||
|
||||
[Header("恢复反馈")]
|
||||
[SerializeField] private MMF_Player _onHeal;
|
||||
|
||||
[Header("移动 / 动作反馈")]
|
||||
[SerializeField] private MMF_Player _onLandImpact;
|
||||
[SerializeField] private MMF_Player _onAttackWhoosh;
|
||||
[SerializeField] private MMF_Player _onJumpLaunch;
|
||||
|
||||
[Header("命名预设(可选)")]
|
||||
[SerializeField] private NamedFeedback[] _namedPresets;
|
||||
|
||||
[Header("音效预设(可选)")]
|
||||
[SerializeField] private NamedFeedback[] _sfxPresets;
|
||||
|
||||
private Dictionary<string, MMF_Player> _presetMap;
|
||||
private Dictionary<string, MMF_Player> _sfxMap;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
_presetMap = BuildMap(_namedPresets);
|
||||
_sfxMap = BuildMap(_sfxPresets);
|
||||
}
|
||||
|
||||
// ── IFeedbackPlayer ──────────────────────────────────────────────────────
|
||||
public void PlayHit(HitWeight weight)
|
||||
{
|
||||
var player = weight switch
|
||||
{
|
||||
HitWeight.Light => _onHitLight,
|
||||
HitWeight.Medium => _onHitMedium,
|
||||
HitWeight.Heavy => _onHitHeavy,
|
||||
_ => _onHitLight,
|
||||
};
|
||||
player?.PlayFeedbacks();
|
||||
}
|
||||
|
||||
public void PlayParrySuccess() => _onParrySuccess?.PlayFeedbacks();
|
||||
public void PlayTakeHit() => _onTakeHit?.PlayFeedbacks();
|
||||
public void PlayDeath() => _onDeath?.PlayFeedbacks();
|
||||
public void PlayHeal() => _onHeal?.PlayFeedbacks();
|
||||
public void PlayLandImpact() => _onLandImpact?.PlayFeedbacks();
|
||||
public void PlayAttackWhoosh() => _onAttackWhoosh?.PlayFeedbacks();
|
||||
public void PlayJumpLaunch() => _onJumpLaunch?.PlayFeedbacks();
|
||||
|
||||
public void TriggerPreset(string presetId)
|
||||
{
|
||||
if (_presetMap.TryGetValue(presetId, out var p))
|
||||
p?.PlayFeedbacks();
|
||||
else
|
||||
Debug.LogWarning($"[PlayerFeedback] 未找到预设 '{presetId}'。");
|
||||
}
|
||||
|
||||
public void PlaySFXById(string sfxId)
|
||||
{
|
||||
if (_sfxMap.TryGetValue(sfxId, out var p))
|
||||
p?.PlayFeedbacks();
|
||||
else
|
||||
Debug.LogWarning($"[PlayerFeedback] 未找到 SFX 预设 '{sfxId}'。");
|
||||
}
|
||||
|
||||
// ── 辅助 ─────────────────────────────────────────────────────────────────
|
||||
private static Dictionary<string, MMF_Player> BuildMap(NamedFeedback[] entries)
|
||||
{
|
||||
var map = new Dictionary<string, MMF_Player>();
|
||||
if (entries == null) return map;
|
||||
foreach (var e in entries)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(e.id))
|
||||
map[e.id] = e.player;
|
||||
}
|
||||
return map;
|
||||
}
|
||||
}
|
||||
|
||||
[System.Serializable]
|
||||
public struct NamedFeedback
|
||||
{
|
||||
public string id;
|
||||
public MMF_Player player;
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/Feedback/PlayerFeedback.cs.meta
Normal file
11
Assets/Scripts/Feedback/PlayerFeedback.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2865735d009e06d4b88c8f81b149b7d0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
3
Assets/Scripts/Feedback/_Placeholder.cs
Normal file
3
Assets/Scripts/Feedback/_Placeholder.cs
Normal file
@@ -0,0 +1,3 @@
|
||||
// Placeholder to prevent asmdef-no-scripts warning.
|
||||
namespace BaseGames.Feedback { }
|
||||
|
||||
11
Assets/Scripts/Feedback/_Placeholder.cs.meta
Normal file
11
Assets/Scripts/Feedback/_Placeholder.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e48c25f6e427fea4facf869cec33a9e3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user