So, I have a new script in my game which is in scene called ACSpineExpressions, which I use to control mouth shapes in Spine at random for my player when speaking:
using UnityEngine;
using System.Collections;
using AC;
using Spine.Unity;
using AC.Spine;
using Timers;
public class ACSpineExpressions : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
InvokeRepeating(nameof(UpdateMouth), 0.1f, 0.2f);
}
// Update is called once per frame
void Update()
{
if (speakingCharacter)
{
//if (speakingCharacter.isTalking)
// Debug.Log("Character: " + speakingCharacter + " isTalking");
}
}
void UpdateMouth()
{
if (!skeletonAnimation)
return;
if (speakingCharacter && speakingCharacter.isTalking)
{
if (Random.Range(0, 100) < 70)
{
//skeletonAnimation.AnimationState.SetAnimation(0, "asd", true);
//skeletonAnimation.AnimationState.AddAnimation(0, "idle", true, 0);
//skeletonAnimation.Skeleton.SetAttachment("mouth shapes", "o");
var attachment = skeletonAnimation.Skeleton.FindSlot("mouth shapes");
if (attachment != null)
{
Debug.Log("blah");
switch (Utils.RandomInt(1, 6))
{
case 1: skeletonAnimation.Skeleton.SetAttachment("mouth shapes", "a, i"); break;
//case 2: skeletonAnimation.Skeleton.SetAttachment("mouth shapes", "c,-d,-g,-k,-n,-r,-s,-y,-z"); break;
case 3: skeletonAnimation.Skeleton.SetAttachment("mouth shapes", "e"); break;
//case 3: skeletonAnimation.Skeleton.SetAttachment("mouth shapes", "f,-v"); break;
//case 5: skeletonAnimation.Skeleton.SetAttachment("mouth shapes", "l,-th"); break;
//case 6: skeletonAnimation.Skeleton.SetAttachment("mouth shapes", "m,-b,-p"); break;
case 4: skeletonAnimation.Skeleton.SetAttachment("mouth shapes", "o"); break;
//case 5: skeletonAnimation.Skeleton.SetAttachment("mouth shapes", "q,-w"); break;
case 5: skeletonAnimation.Skeleton.SetAttachment("mouth shapes", "u"); break;
}
//clear mouth
TimersManager.SetTimer(gameObject, 0.15f, 0, delegate
{
skeletonAnimation.Skeleton.SetAttachment("mouth shapes", "mouth");
});
}
else
{
Debug.Log("NO MOUTH SHAPES FOR THIS POSE!");
}
}
}
}
void OnEnable()
{
EventManager.OnStartSpeech += GetSpeech;
EventManager.OnStopSpeech += OnStopSpeech;
}
void OnDisable()
{
EventManager.OnStartSpeech -= GetSpeech;
EventManager.OnStopSpeech -= OnStopSpeech;
}
AC.Char speakingCharacter;
SkeletonAnimation skeletonAnimation;
void GetSpeech(AC.Char speaker, string speechText, int lineID)
{
Debug.Log("Character: " + speaker + ", Text: " + speechText + ", lineID: " + lineID);
skeletonAnimation = speaker.GetComponentInChildren<SkeletonAnimation>();
DirectionMapper directionMapper = speaker.GetComponent<DirectionMapper>();
Debug.Log("skeletonDataAsset: " + directionMapper.skeletonAnimation.skeletonDataAsset);
speakingCharacter = speaker;
}
void OnStopSpeech(AC.Char speaker)
{
Debug.Log("Character: " + speaker + " stopped talking");
}
}
However, my Skin Setter script replaces the skin every frame, and therefore my facial animations won't be set. Arew you able to help me adapt my Skin Setter script to make this work?
using UnityEngine;
using Spine;
using Spine.Unity;
public class SkinSetter : MonoBehaviour
{
public string[] newSkinNames = new string[0];
public void LateUpdate ()
{
SkeletonAnimation skeletonAnimation = GetComponentInChildren<SkeletonAnimation> ();
if (skeletonAnimation == null) return;
Skeleton skeleton = skeletonAnimation.Skeleton;
Skin newSkin = new Skin ("new-skin"); // 1. Create a new empty skin
foreach (string newSkinName in newSkinNames)
{
Skin existingSkin = skeleton.Data.FindSkin (newSkinName);
if (existingSkin != null)
{
newSkin.AddSkin (existingSkin);
}
else
{
Debug.LogWarning ("Cannot find Skin with name '" + newSkinName + "'", skeletonAnimation);
}
}
skeleton.SetSkin (newSkin);
skeleton.SetSlotsToSetupPose ();
}
}
It looks like you're new here. If you want to get involved, click one of these buttons!
Comments
This isn't an AC issue - AC is only involved insofar as you setting the skeletonAnimation / speakingCharacter variables.
If you want the second script to be dependent on the first (i.e. don't run if the first is running), make speakingCharacter public and then check its value at the top of the LateUpdate function, i.e.: