fix: bind fighter animator controller in lobby

This commit is contained in:
ud18010
2026-07-30 17:15:09 +08:00
parent e9efa8a567
commit d3c4bba5b2
5 changed files with 178 additions and 1 deletions
@@ -0,0 +1,72 @@
using System;
using System.Collections;
using UnityEngine;
using UObject = UnityEngine.Object;
#if UNITY_EDITOR
using UnityEditor;
#endif
namespace XGame.ActorBehavior
{
public static class ActorBehaviorAnimatorControllerPaths
{
public static string GetControllerPath(string catalogType)
{
return string.Equals(catalogType, LobbyActorBehaviorRuntime.DefaultCatalogType, StringComparison.OrdinalIgnoreCase)
? "Assets/Game/Art/Actor/Controller/fighter.controller"
: null;
}
}
public static class ActorBehaviorAnimatorControllerLoader
{
public static IEnumerator ApplyController(string catalogType, Animator animator, Action<bool> onApplied = null)
{
if (animator == null)
{
onApplied?.Invoke(false);
yield break;
}
string controllerPath = ActorBehaviorAnimatorControllerPaths.GetControllerPath(catalogType);
if (string.IsNullOrEmpty(controllerPath))
{
onApplied?.Invoke(false);
yield break;
}
RuntimeAnimatorController controller = LoadControllerInEditor(controllerPath);
if (controller == null)
{
UObject loaded = null;
yield return XGame.XResLoader.coLoadRes(controllerPath, typeof(RuntimeAnimatorController), obj => loaded = obj);
controller = loaded as RuntimeAnimatorController;
}
if (controller == null)
{
Debug.LogWarning("[ActorBehaviorAnimatorControllerLoader] controller load failed: " + controllerPath);
onApplied?.Invoke(false);
yield break;
}
if (animator.runtimeAnimatorController != controller)
{
animator.runtimeAnimatorController = controller;
animator.Rebind();
animator.Update(0f);
}
onApplied?.Invoke(true);
}
private static RuntimeAnimatorController LoadControllerInEditor(string controllerPath)
{
#if UNITY_EDITOR
return AssetDatabase.LoadAssetAtPath<RuntimeAnimatorController>(controllerPath);
#else
return null;
#endif
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0a9d2d021b3b4de0a1e9437e62a08f6a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -56,6 +56,10 @@ namespace XGame
private const float CameraMouseZoomSensitivity = 1.4f;
private const float CameraPinchZoomSensitivity = 0.015f;
private const float CameraFollowSharpness = 12f;
private const string FighterStandState = "140_stand01_qt";
private const string FighterWalkState = "140_walk01_qt";
private const string LegacyStandState = "Stand";
private const string LegacyWalkState = "Walk";
private readonly Dictionary<int, Avatar> avatars = new Dictionary<int, Avatar>();
private readonly Dictionary<int, GameObject> prefabCache = new Dictionary<int, GameObject>();
@@ -805,7 +809,11 @@ namespace XGame
{
return;
}
string state = moving ? "Walk" : "Stand";
string state = ResolveMoveState(avatar.Animator, moving);
if (string.IsNullOrEmpty(state))
{
return;
}
if (avatar.AnimState == state)
{
return;
@@ -814,6 +822,25 @@ namespace XGame
avatar.Animator.CrossFade(state, 0.1f);
}
private static string ResolveMoveState(Animator animator, bool moving)
{
string fighterState = moving ? FighterWalkState : FighterStandState;
if (HasAnimatorState(animator, fighterState))
{
return fighterState;
}
string legacyState = moving ? LegacyWalkState : LegacyStandState;
return HasAnimatorState(animator, legacyState) ? legacyState : null;
}
private static bool HasAnimatorState(Animator animator, string state)
{
return animator != null
&& animator.runtimeAnimatorController != null
&& animator.HasState(0, Animator.StringToHash(state));
}
private void UpdateJoystick()
{
joystick = Vector2.zero;
@@ -994,6 +1021,43 @@ namespace XGame
actorBehaviorRuntime.RegisterOrUpdateActor(avatar.PlayerId, avatar.Obj.transform.position, avatar.Obj.transform.forward);
actorBehaviorRuntime.SwitchActorCatalog(avatar.PlayerId, LobbyActorBehaviorRuntime.DefaultCatalogType);
actorBehaviorPresentation.RegisterActor(avatar.PlayerId, avatar.Animator, avatar.Obj.transform, avatar.Obj.transform);
ApplyActorBehaviorAnimatorController(avatar);
}
private void ApplyActorBehaviorAnimatorController(Avatar avatar)
{
if (avatar == null || avatar.Obj == null || avatar.Animator == null)
{
return;
}
StartCoroutine(ApplyActorBehaviorAnimatorControllerAsync(
avatar.PlayerId,
avatar.Obj,
avatar.Animator,
LobbyActorBehaviorRuntime.DefaultCatalogType));
}
private IEnumerator ApplyActorBehaviorAnimatorControllerAsync(
int playerId,
GameObject actorObject,
Animator animator,
string catalogType)
{
bool applied = false;
yield return ActorBehaviorAnimatorControllerLoader.ApplyController(catalogType, animator, value => applied = value);
if (!applied || actorObject == null || animator == null)
{
yield break;
}
if (!avatars.TryGetValue(playerId, out Avatar avatar) || avatar.Obj != actorObject || avatar.Animator != animator)
{
yield break;
}
avatar.AnimState = null;
SetMoveState(avatar, avatar.Moving);
}
private void UpdateActorBehaviorActor(Avatar avatar)