Table of Contents

Class CharacterAppearanceManager

Namespace
FishMMO.Shared
Assembly
FishMMO.Shared.dll

Manages character visual appearance: bone scaling for body proportions, blend shape synchronization, and appearance data serialization.

Bone scaling is separated into a global Height pass and individual body-part adjustments. Height scales all height-affecting bones uniformly. Individual sliders (TorsoLength, LegLength, ArmLength) apply additional proportional tweaks on top. This means a Dwarf with Height=0.75 and LegLength=0.70 has legs at 0.75 * 0.70 = 0.525x scale — intentionally shorter than the already reduced height.

All operations are client-only.

public class CharacterAppearanceManager : CharacterBehaviour, ICharacterAppearanceManager, ICharacterBehaviour, IModelReadyHandler
Inheritance
Object
Component
Behaviour
MonoBehaviour
NetworkBehaviour
CharacterAppearanceManager
Implements
Inherited Members
NetworkBehaviour.IsSpawned
NetworkBehaviour.ComponentIndex
NetworkBehaviour.NetworkObject
NetworkBehaviour.MAXIMUM_NETWORKBEHAVIOURS
NetworkBehaviour.UNSET_NETWORKBEHAVIOUR_ID
NetworkBehaviour.ToString()
NetworkBehaviour.Reset()
NetworkBehaviour.OnValidate()
NetworkBehaviour.IsBehaviourReconciling
NetworkBehaviour.ClearReplicateCache()
NetworkBehaviour.CreateReconcile()
NetworkBehaviour.Reconcile_Reader<T>(PooledReader, ref T)
NetworkBehaviour.OnStartServerCalled
NetworkBehaviour.OnStartClientCalled
NetworkBehaviour.WritePayload(NetworkConnection, Writer)
NetworkBehaviour.ReadPayload(NetworkConnection, Reader)
NetworkBehaviour.OnStartNetwork()
NetworkBehaviour.OnStopNetwork()
NetworkBehaviour.OnStartServer()
NetworkBehaviour.OnStopServer()
NetworkBehaviour.OnOwnershipServer(NetworkConnection)
NetworkBehaviour.OnSpawnServer(NetworkConnection)
NetworkBehaviour.OnDespawnServer(NetworkConnection)
NetworkBehaviour.OnStartClient()
NetworkBehaviour.OnStopClient()
NetworkBehaviour.OnOwnershipClient(NetworkConnection)
NetworkBehaviour.ClearBuffedRpcs()
NetworkBehaviour.ExcludeOwnerFromUnbufferedObserversRpcs
NetworkBehaviour.IsClientOnly
NetworkBehaviour.IsServerOnly
NetworkBehaviour.IsHost
NetworkBehaviour.IsClient
NetworkBehaviour.IsServer
NetworkBehaviour.IsDeinitializing
NetworkBehaviour.NetworkManager
NetworkBehaviour.ServerManager
NetworkBehaviour.ClientManager
NetworkBehaviour.ObserverManager
NetworkBehaviour.TransportManager
NetworkBehaviour.TimeManager
NetworkBehaviour.SceneManager
NetworkBehaviour.PredictionManager
NetworkBehaviour.RollbackManager
NetworkBehaviour.NetworkObserver
NetworkBehaviour.IsClientInitialized
NetworkBehaviour.IsClientStarted
NetworkBehaviour.IsClientOnlyInitialized
NetworkBehaviour.IsClientOnlyStarted
NetworkBehaviour.IsServerInitialized
NetworkBehaviour.IsServerStarted
NetworkBehaviour.IsServerOnlyInitialized
NetworkBehaviour.IsServerOnlyStarted
NetworkBehaviour.IsHostInitialized
NetworkBehaviour.IsHostStarted
NetworkBehaviour.IsOffline
NetworkBehaviour.IsNetworked
NetworkBehaviour.GetIsNetworked()
NetworkBehaviour.IsManagerReconciling
NetworkBehaviour.Observers
NetworkBehaviour.IsOwner
NetworkBehaviour.IsController
NetworkBehaviour.HasAuthority
NetworkBehaviour.Owner
NetworkBehaviour.OwnerId
NetworkBehaviour.ObjectId
NetworkBehaviour.LocalConnection
NetworkBehaviour.OwnerMatches(NetworkConnection)
NetworkBehaviour.Despawn(GameObject, DespawnType?)
NetworkBehaviour.Despawn(NetworkObject, DespawnType?)
NetworkBehaviour.Despawn(DespawnType?)
NetworkBehaviour.Spawn(GameObject, NetworkConnection, Scene)
NetworkBehaviour.Spawn(NetworkObject, NetworkConnection, Scene)
NetworkBehaviour.RemoveOwnership()
NetworkBehaviour.GiveOwnership(NetworkConnection)
NetworkBehaviour.GetInstance<T>()
NetworkBehaviour.TryRegisterInstance<T>(T)
NetworkBehaviour.UnregisterInstance<T>()
NetworkBehaviour.CanLog(LoggingType)
MonoBehaviour.IsInvoking()
MonoBehaviour.CancelInvoke()
MonoBehaviour.StopCoroutine(Coroutine)
MonoBehaviour.StopAllCoroutines()
MonoBehaviour.destroyCancellationToken
MonoBehaviour.useGUILayout
MonoBehaviour.didStart
MonoBehaviour.didAwake
MonoBehaviour.runInEditMode
Behaviour.enabled
Behaviour.isActiveAndEnabled
Component.GetComponent<T>()
Component.TryGetComponent<T>(out T)
Component.GetComponentInChildren<T>()
Component.GetComponentsInChildren<T>()
Component.GetComponentInParent<T>()
Component.GetComponentsInParent<T>()
Component.GetComponents<T>()
Component.GetComponentIndex()
Component.CompareTag(TagHandle)
Component.transform
Component.transformHandle
Component.gameObject
Component.tag
Object.GetEntityId()
Object.GetInstanceID()
Object.GetHashCode()
Object.InstantiateAsync<T>(T)
Object.InstantiateAsync<T>(T, Transform)
Object.InstantiateAsync<T>(T, Vector3, Quaternion)
Object.InstantiateAsync<T>(T, Transform, Vector3, Quaternion)
Object.Instantiate(Object, Vector3, Quaternion)
Object.Instantiate(Object, Vector3, Quaternion, Transform)
Object.Instantiate(Object)
Object.Instantiate(Object, Scene)
Object.Instantiate<T>(T, InstantiateParameters)
Object.Instantiate<T>(T, Vector3, Quaternion, InstantiateParameters)
Object.Instantiate(Object, Transform)
Object.Instantiate<T>(T)
Object.Instantiate<T>(T, Vector3, Quaternion)
Object.Instantiate<T>(T, Vector3, Quaternion, Transform)
Object.Instantiate<T>(T, Transform)
Object.Destroy(Object)
Object.DestroyImmediate(Object)
Object.DontDestroyOnLoad(Object)
Object.DestroyObject(Object)
Object.FindObjectsOfType<T>()
Object.FindObjectsByType<T>(FindObjectsSortMode)
Object.FindObjectsByType<T>(FindObjectsInactive, FindObjectsSortMode)
Object.FindObjectOfType<T>()
Object.FindFirstObjectByType<T>()
Object.FindAnyObjectByType<T>()
Object.FindFirstObjectByType<T>(FindObjectsInactive)
Object.FindAnyObjectByType<T>(FindObjectsInactive)
Object.FindObjectsByType<T>()
Object.FindObjectsByType<T>(FindObjectsInactive)
Object.name
Object.hideFlags

Methods

ApplyAppearanceData(CharacterAppearanceData)

Restores appearance from a serialized data snapshot.

public void ApplyAppearanceData(CharacterAppearanceData data)

Parameters

data CharacterAppearanceData

The appearance data to apply.

ApplyRaceProportions(RaceProportions)

Applies race default proportions via bone scaling. Called once when the character model is instantiated.

public void ApplyRaceProportions(RaceProportions proportions)

Parameters

proportions RaceProportions

The race proportion values to apply.

GetAppearanceData()

Returns a snapshot of the character's current appearance.

public CharacterAppearanceData GetAppearanceData()

Returns

CharacterAppearanceData

A snapshot with all proportions, blend shapes, and equipped item IDs.

OnModelReady()

Called when the character model has finished loading. At this point, the skeleton, Animator, and body region renderers are available.

public void OnModelReady()

OnStartCharacter()

Initial discovery attempt. May not find everything if model hasn't loaded. Full initialization deferred to OnModelReady().

public override void OnStartCharacter()

RegisterEquipmentRenderer(SkinnedMeshRenderer)

Registers an equipment renderer for blend shape syncing. Called by EquipmentVisualController when an item is equipped.

public void RegisterEquipmentRenderer(SkinnedMeshRenderer renderer)

Parameters

renderer SkinnedMeshRenderer

ResetState(bool)

Drops the appearance discovered from the current model before the object is pooled.

public override void ResetState(bool asServer)

Parameters

asServer bool

True if called on the server.

Remarks

OnModelReady() clears the body renderers and the skeleton on its way to re-discovering them, but it only runs once the NEXT model has finished loading, and the three things it does not touch have no other writer at all: the blend shape values, the equipment renderers registered by EquipmentVisualController, and FishMMO.Shared.CharacterAppearanceManager.currentAppearance itself.

Left in place, the blend shapes are re-applied wholesale to the next occupant's model — ReapplyBlendShapes walks that dictionary and writes every entry — so a recycled object carried the previous character's face and body sliders onto a different character. The equipment renderer list is worse than stale: its entries belong to renderers that the visual controller destroys on teardown, so every later blend shape write iterated a list of dead Unity objects.

SetBlendShape(string, float)

Sets a blend shape value on all body region renderers and all equipped equipment renderers that have a matching blend shape name.

public void SetBlendShape(string name, float value)

Parameters

name string

Blend shape name (e.g., "Weight", "MuscleMass").

value float

Blend weight (0-100).

SyncBlendShapesToEquipment(SkinnedMeshRenderer)

Pushes current body blend shape values to an equipment SkinnedMeshRenderer. Only applies blend shapes that exist on the equipment mesh. Called when new equipment is equipped.

public void SyncBlendShapesToEquipment(SkinnedMeshRenderer equipmentRenderer)

Parameters

equipmentRenderer SkinnedMeshRenderer

The newly equipped item's SkinnedMeshRenderer.

UnregisterEquipmentRenderer(SkinnedMeshRenderer)

Unregisters an equipment renderer. Called by EquipmentVisualController when an item is unequipped.

public void UnregisterEquipmentRenderer(SkinnedMeshRenderer renderer)

Parameters

renderer SkinnedMeshRenderer