Skip to content

Documentation

Nunchuk/ToasterOven edited this page May 5, 2023 · 2 revisions

Here I will document (probably) everything you can do when Importing Emotes/EmoteSkeletons.

Importing Emote Skeletons

Importing Animations

When Animation Plays

When Emote Spot Joined

BoneMapper Useful Info

CustomAnimationClip Useful Info

Possible use cases

Importing Emote Skeletons

CustomEmotesAPI.ImportArmature
  • GameObject bodyPrefab (This is the bodyPrefab used in game already)
  • GameObject rigToAnimate (This is your EmoteSkeleton)
  • bool jank (Optional and deprecated, only use this as a last resort, but it might get your skeleton working)
  • int meshPos = 0 (Mostly pointless, but if you know exactly the spot your actual animating skinnedmeshrenderer is, you could save a few nanosecconds by setting this manually)
  • bool hideMeshes = true (This should be left alone unless you are debugging. With this on, any meshes which are part of your emote skeleton will be hidden)

Importing Animations

CustomEmotesAPI.AddCustomAnimation
  • AnimationClip[] animationClip (Array of animation clips which will play in your animation, largely dependent on startPref/joinPref. The first item in the array will be what displays in game, IE: the emote wheel)
  • bool looping (Whether or not animationClip is looping, secondaryAnimation is always assumed to loop because why else would you use it)
  • string[] _wwiseEventName = null (Start events for wwise, called when an animation starts)
  • string[] _wwiseStopEvent = null (Stop events for wwise, should be equal in length to _wwiseEventName, called when an animation ends)
  • HumanBodyBones[] rootBonesToIgnore = null (Array of humanbodybones, the bone in question, and any child bones will be ignored while the animation is playing)
  • HumanBodyBones[] soloBonesToIgnore = null (Array of humanbodybones, the bone in question will be ignored while the animation is playing)
  • AnimationClip[] secondaryAnimation = null (Array of animation clips, always assumed to loop and should be used if your looping animation has startup motion that you don't want to be in the loop, should be equal in length to animationClip)
  • bool dimWhenClose = false (Creates a 20m sphere around the emote which will dim music as you get closer and closer to the source)
  • bool stopWhenMove = false (Stops animation when you move [slightly untested due to non-existent demand, please reach out if you have issues])
  • bool stopWhenAttack = false (Stops animation when you attack [slightly untested due to non-existent demand, please reach out if you have issues])
  • bool visible = true (Lets you remove an animation from the normal animation list, this would be ideal if you want to setup animations to a keybind and nothing else)
  • bool syncAnim = false (Syncs animation motion between all BoneMappers)
  • bool syncAudio = false (Syncs audio between all BoneMappers)
  • int startPref = -1 (Spot in animationClip array where a BoneMapper will play when there is no other instance of said emote playing, -1 is random, -2 is sequential, anything else is what you make it to be)
  • int joinPref = -1 (Spot in animationClip array where a BoneMapper will play when there is at least one other instance of said emote playing, -1 is random, -2 is sequential, anything else is what you make it to be)
  • JoinSpot[] joinSpots = null (Array of join spots which will appear when the animation is playing)
  • Action<BoneMapper> customPostEventCodeSync See Advanced Mode beneath for more info
  • Action<BoneMapper> customPostEventCodeNoSync See Advanced Mode beneath for more info
JoinSpot
  • string _name (Name of join spot)
  • Vector3 _position (Position of join spot relative to BoneMapper)
  • Vector3 _rotation (Rotation of join spot relative to BoneMapper)
  • Vector3 _scale (Scale of join spot relative to BoneMapper)

When Animation Plays

CustomEmotesAPI.animChanged
  • string newAnimation (The name of the animation that played, "none" is well, none)
  • BoneMapper mapper (The BoneMapper that played said animation)

When Emote Spot Joined

CustomEmotesAPI.emoteSpotJoined_Body
  • GameObject emoteSpot (The emoteSpot that has been joined, you can get the name and such from this. Emotespots always have an EmoteLocation component attached)
  • BoneMapper joiner (The BoneMapper which joined the emoteSpot)
  • BoneMapper host (The BoneMapper which owns the emoteSpot)
CustomEmotesAPI.emoteSpotJoined_Prop
  • Same as above, but for internal reasons they are separate calls.
EmoteLocation
  • SetEmoterAndHideLocation(BoneMapper boneMapper) (If you call this, it will hide the emote spot until said BoneMapper changes animations)

BoneMapper Useful Info

  • public static Dictionary<string, CustomAnimationClip> animClips (List of all CustomAnimationClips)
  • public CustomAnimationClip currentClip = null (current CustomAnimationClip)
  • public CustomAnimationClip prevClip = null (previous CustomAnimationClip)
  • public bool local = false (Whether or not BoneMapper is the local user)
  • public List<GameObject> props (Props which you can assign to a BoneMapper, deleted every time a new animation is played, unless...)
  • public bool preserveProps = false (If true, prevents props from being cleared at the start of a new animation, then resets back to false)
  • public float scale = 1.0f (Auto set during ImportArmature, determines how big the survivor is in relation to Bandit. This is used for scaling props or scaling the character during animations that keep everyone the same size. If you are not happy with auto setting since it's not a perfect system, you can change it after you call ImportArmature)
  • public float autoWalkSpeed = 0 (NOTE: this would more accurately be maxWalkSpeed, however I do not want to break existing code so it will stay as is. Reset to 0 whenever a new animation plays. Sets auto walking speed to whatever value specified, this can theoretically let you bypass your max move speed, however...)
  • public bool overrideMoveSpeed = false (Reset to false whenever a new animation plays. When on, prevents user from performing normal movement actions (except jumping) during animation, this, in combination with autoWalkSpeed, let's a user create an autowalk which will always be consistent in speed)
  • public bool autoWalk = false (Reset to false whenever a new animation plays. When on, causes BoneMapper to automatically walk forward)
  • public GameObject currentEmoteSpot = null (The current emote spot (if any) that is being used by the BoneMapper)
  • public bool worldProp = false (Whether or not the BoneMapper is a world prop)
  • public GameObject parentGameObject (For some animations, you might want to lock a character to a specific gameobject, providing a ton more options for movement, this is automatically removed at the start of any animation unless...)
  • public bool preserveParent = false (if set to true, switches back to false and prevents the parentGameObject from being decoupled)
BoneMapper.AssignParentGameObject
  • GameObject youAreTheFather (The GameObject you are assigning as the parent. Unless you are using this in combination with preserveParent, it is recommended to also add this GameObject to the BoneMapper's props)
  • bool lockPosition (Locks position of the character to youAreTheFather)
  • bool lockRotation (Locks rotation of the character to youAreTheFather)
  • bool lockScale (Locks scale of the character to youAreTheFather)
  • bool scaleAsBandit = true (Only relevant if lockScale is on, uses the scale value from earlier to scale the character as close to bandit's height as possible)
  • bool disableCollider = true (Disables the character's physics collider (not hurtbox) until the parent is unassigned, this prevents clipping issues if you lock two characters in the same spot)
BoneMapper.ScaleProps
  • Uses the scale value from earlier to scale any assigned props up or down to the character's size.
BoneMapper.SetAnimationSpeed
  • float speed (Sets the animator speed, reset to 1 whenever an emote plays so set it after you start an animation)
BoneMapper.SetAutoWalk
  • float speed (sets autoWalkSpeed)
  • bool overrideBaseMovement (sets overrideMoveSpeed)
  • bool autoWalk (sets autoWalk
  • Just a helper function, not much to see here

CustomAnimationClip Useful Info

  • public int syncPos (Sync position used in the following two items, however do note, most of this is done automatically and there are only a couple cases where you will want to mess with this, but they do exist)
  • public static List<float> syncTimer (Sync timer for animation's playing)
  • public static List<int> syncPlayerCount (How many current characters are performing an animation)

Possible Use Cases

  • If you are importing an EmoteSkeleton, consider subscribing to the animChanged event, and check if the BoneMapper.name is equal to the emoteskeleton you imported, then if true, also check if the played animation is "none"/not "none". Depending on the outcome, you can set it to hide weapon meshes on your character while they animate.
  • If you have multiple SEPERATE emotes but still want them all to sync together, consider keeping track of the syncPos of the first CustomAnimationClip you setup and then applying it to all other animations you want to sync up. You could grab it by calling something along the lines of: int syncpos = BoneMapper.animClips[emoteName].syncPos
  • If you join at a join spot, you will probably want to lock your position in with the host. Consider setting up a listener on emoteSpotJoined_Body. If the emotespot's name is equal to whatever you called it, create a new GameObject, we'll call it G. First off, play whatever animation is required, then assign G to the joinerMapper's props. Set G's parent to the hostMapper's transform and setup G's local transform data to be correct, possible all Vector3.zero. Finally on joinerMapper, call AssignParentGameObject with G as the parent.
  • If you subscribe to animChanged, you can check if the newAnimation is equal to "AutoWalkAnimation" (just for example, this isn't a real animation) and if so, call SetAutoWalk on the BoneMapper.

Advanced Mode

  • In the event that you want to receive callbacks from wwise events when you are starting audio, you would probably want to change the PostEvent's that happen when emotes play. You can do this by utilizing the customPostEventCodeSync/NoSync in AnimationClipParams for any given emote. Sync/NoSync refers to whether or not the audio on your emote is supposed to sync or not. Bigma Lalls
  • As you can see in this image, I "overwrite" the PostEvent for when the audio for this specific emote plays, no other emotes will be affected unless you specify them in their own creation.
  • IMPORTANT NOTE: I HIGHLY recommend you insert the following code as a minimum requirement for emotes with syncing audio: AkSoundEngine.PostEvent(BoneMapper.startEvents[mapper.currentClip.syncPos][mapper.currEvent], CustomEmotesAPI.audioContainers[mapper.currentClip.syncPos]);
  • IMPORTANT NOTE: I HIGHLY recommend you insert the following code as a minimum requirement for emotes without syncing audio: AkSoundEngine.PostEvent(BoneMapper.startEvents[mapper.currentClip.syncPos][mapper.currEvent], mapper.gameObject);
  • If you do not have these in their respective overrides as a minimum, you will probably run into errors. However, none of this will stop you from inserting callbacks and such into the function itself.