/**
* Copyright(c) Live2D Inc. All rights reserved.
*
* Use of this source code is governed by the Live2D Open Software license
* that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html.
*/
using Live2D.Cubism.Core;
using Live2D.Cubism.Framework;
using Live2D.Cubism.Framework.Expression;
using Live2D.Cubism.Framework.Motion;
using Live2D.Cubism.Framework.Raycasting;
using System;
using System.Collections.Generic;
using UnityEngine;
namespace Live2D.Cubism.Samples.OriginalWorkflow.Demo
{
[RequireComponent(typeof(CubismMotionController))]
[RequireComponent(typeof(CubismRaycaster))]
public class CubismSampleController : MonoBehaviour
{
///
/// MotionController to be operated.
///
private CubismMotionController _motionController;
///
/// ExpressionController to be operated.
///
private CubismExpressionController _expressionController;
///
/// Operation animation clip from the inspector.
///
[SerializeField]
private AnimationClip _bodyAnimation;
///
/// Array of motion set in tapbody.
///
[SerializeField]
private AnimationClip[] _tapBodyMotions;
///
/// Motion set in loop motion.
///
private AnimationClip _loopMotion;
///
/// List of Drawables info.
///
private List _hasHitDrawables;
///
/// Component that performs ray judgment on Drawables of model.
///
private CubismRaycaster _raycaster;
///
/// Raycast Hit Results.
///
private CubismRaycastHit[] _raycastResults;
///
/// Enumeration type for hit area discrimination.
///
private enum HitArea
{
Head,
Body
}
///
/// Structure that stores Drawable information for which hit area is specified.
///
private struct HitDrawableInfomation
{
///
/// Drawable with component set.
///
public CubismDrawable drawable;
///
/// HitArea.
///
public HitArea hitArea;
}
///
/// Load model.
///
private void Start()
{
var model = this.FindCubismModel();
// Get components.
_motionController = model.GetComponent();
_expressionController = model.GetComponent();
_raycaster = model.GetComponent();
// Set behavior at the end of animation.
_motionController.AnimationEndHandler = AnimationEnded;
// Get up to 4 results of collision detection.
_raycastResults = new CubismRaycastHit[4];
// Cache the drawable in which the component is set.
{
_hasHitDrawables = new List();
var hitAreas = Enum.GetValues(typeof(HitArea));
var drawables = model.Drawables;
for (var i = 0; i < hitAreas.Length; i++)
{
for (var j = 0; j < drawables.Length; j++)
{
var cubismHitDrawable = drawables[j].GetComponent();
if (cubismHitDrawable)
{
if (cubismHitDrawable.Name == hitAreas.GetValue(i).ToString())
{
var hitDrawable = new HitDrawableInfomation();
hitDrawable.drawable = drawables[j];
hitDrawable.hitArea = (HitArea)i;
_hasHitDrawables.Add(hitDrawable);
break;
}
}
}
}
}
}
///
/// Update.
///
private void Update()
{
// Play if animation is specified.
SpecifiedAnimationCheck();
if(!Input.GetMouseButtonDown(0))
{
if (!_motionController.IsPlayingAnimation())
{
Debug.Log("Body animation : Play : " + _loopMotion.name);
_motionController.PlayAnimation(_loopMotion, priority: CubismMotionPriority.PriorityIdle);
}
return;
}
// Cast ray from pointer position.
var ray = Camera.main.ScreenPointToRay(Input.mousePosition);
var hitCount = _raycaster.Raycast(ray, _raycastResults);
// Motion playback according to the hit location.
for (var i = 0; i < hitCount; i++)
{
var hitDrawable = _raycastResults[i].Drawable;
for (var j = 0; j < _hasHitDrawables.Count; j++)
{
if (hitDrawable == _hasHitDrawables[j].drawable)
{
var hitArea = _hasHitDrawables[j].hitArea;
// Tap body.
if (hitArea == HitArea.Body)
{
// Decide motion to play at random.
var motionIndex = UnityEngine.Random.Range(0, _tapBodyMotions.Length);
Debug.Log("Tap body : Play : " + _tapBodyMotions[motionIndex].name);
_motionController.PlayAnimation(_tapBodyMotions[motionIndex], isLoop: false, priority:CubismMotionPriority.PriorityNormal);
}
// Tap head.
else if (hitArea == HitArea.Head)
{
// Decide expression motion to play at random.
var expressionNum = _expressionController.ExpressionsList.CubismExpressionObjects.Length;
var expressionIndex = UnityEngine.Random.Range(0, expressionNum);
_expressionController.CurrentExpressionIndex = expressionIndex;
Debug.Log("Tap head : Play : " + _expressionController.ExpressionsList.CubismExpressionObjects[expressionIndex].name);
}
break;
}
}
}
}
///
/// Check the specified animation and play it.
///
private void SpecifiedAnimationCheck()
{
if(_bodyAnimation != _loopMotion)
{
_loopMotion = _bodyAnimation;
Debug.Log("Body animation : Play : " + _loopMotion.name);
_motionController.PlayAnimation(_loopMotion, priority:CubismMotionPriority.PriorityIdle);
}
}
///
/// Called at the end of the animation.
///
///
private void AnimationEnded(int instanceId)
{
Debug.Log("AnimationEnded");
}
}
}