live2D (sdk가 6.5 미지원으로 sprite로 대응)

This commit is contained in:
2026-08-08 22:13:54 +09:00
parent 9ce6930772
commit 8a4a001fe0
4278 changed files with 287426 additions and 18 deletions

View File

@@ -0,0 +1,181 @@
/**
* 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 UnityEngine;
namespace Live2D.Cubism.Framework.MouthMovement
{
/// <summary>
/// Real-time <see cref="CubismMouthController"/> input from <see cref="AudioSource"/>s.
/// </summary>
[RequireComponent(typeof(CubismMouthController))]
public sealed class CubismAudioMouthInput : MonoBehaviour
{
/// <summary>
/// Audio source to sample.
/// </summary>
[SerializeField]
public AudioSource AudioInput;
/// <summary>
/// Sampling quality.
/// </summary>
[SerializeField]
public CubismAudioSamplingQuality SamplingQuality;
/// <summary>
/// Audio gain.
/// </summary>
[Range(1.0f, 10.0f)]
public float Gain = 1.0f;
/// <summary>
/// Smoothing.
/// </summary>
[Range(0.0f, 1.0f)]
public float Smoothing;
/// <summary>
/// Current samples.
/// </summary>
private float[] Samples { get; set; }
/// <summary>
/// Last root mean square.
/// </summary>
private float LastRms { get; set; }
/// <summary>
/// Buffer for <see cref="Mathf.SmoothDamp(float, float, ref float, float)"/> velocity.
/// </summary>
// ReSharper disable once InconsistentNaming
private float VelocityBuffer;
/// <summary>
/// Targeted <see cref="CubismMouthController"/>.
/// </summary>
private CubismMouthController Target { get; set; }
/// <summary>
/// True if instance is initialized.
/// </summary>
private bool IsInitialized
{
get { return Samples != null; }
}
/// <summary>
/// Makes sure instance is initialized.
/// </summary>
private void TryInitialize()
{
// Return early if already initialized.
if (IsInitialized)
{
return;
}
// Initialize samples buffer.
switch (SamplingQuality)
{
case (CubismAudioSamplingQuality.VeryHigh):
{
Samples = new float[256];
break;
}
case (CubismAudioSamplingQuality.Maximum):
{
Samples = new float[512];
break;
}
default:
{
Samples = new float[256];
break;
}
}
// Cache target.
Target = GetComponent<CubismMouthController>();
}
#region Unity Event Handling
/// <summary>
/// Samples audio input and applies it to mouth controller.
/// </summary>
private void Update()
{
// 'Fail' silently.
if (AudioInput == null)
{
return;
}
// Sample audio.
var total = 0f;
AudioInput.GetOutputData(Samples, 0);
for (var i = 0; i < Samples.Length; ++i)
{
var sample = Samples[i];
total += (sample * sample);
}
// Compute root mean square over samples.
var rms = Mathf.Sqrt(total / Samples.Length) * Gain;
// Clamp root mean square.
rms = Mathf.Clamp(rms, 0.0f, 1.0f);
// Smooth rms.
rms = Mathf.SmoothDamp(LastRms, rms, ref VelocityBuffer, Smoothing * 0.1f);
// Set rms as mouth opening and store it for next evaluation.
Target.MouthOpening = rms;
LastRms = rms;
}
/// <summary>
/// Initializes instance.
/// </summary>
private void OnEnable()
{
TryInitialize();
}
#endregion
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 090aae4f094a5c641b26e9e4b9da2604
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,31 @@
/**
* 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.
*/
namespace Live2D.Cubism.Framework.MouthMovement
{
/// <summary>
/// Audio sampling quality.
/// </summary>
public enum CubismAudioSamplingQuality
{
/// <summary>
/// High quality.
/// </summary>
High,
/// <summary>
/// Very high quality.
/// </summary>
VeryHigh,
/// <summary>
/// Insane quality.
/// </summary>
Maximum
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: fe9ba562aae52fe4396dc4b1e2f12412
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,82 @@
/**
* 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 UnityEngine;
namespace Live2D.Cubism.Framework.MouthMovement
{
/// <summary>
/// Automatic mouth movement.
/// </summary>
public sealed class CubismAutoMouthInput : MonoBehaviour
{
/// <summary>
/// Timescale.
/// </summary>
[SerializeField]
public float Timescale = 10f;
/// <summary>
/// Target controller.
/// </summary>
private CubismMouthController Controller { get; set; }
/// <summary>
/// Current time.
/// </summary>
private float T { get; set; }
/// <summary>
/// Resets the input.
/// </summary>
public void Reset()
{
T = 0f;
}
#region Unity Event Handling
/// <summary>
/// Called by Unity. Initializes input.
/// </summary>
private void Start()
{
Controller = GetComponent<CubismMouthController>();
}
/// <summary>
/// Called by Unity. Updates controller.
/// </summary>
/// <remarks>
/// Make sure this method is called after any animations are evaluated.
/// </remarks>
private void LateUpdate()
{
// Fail silently.
if (Controller == null)
{
return;
}
// Progress time.
T += (Time.deltaTime * Timescale);
// Evaluate.
Controller.MouthOpening = Mathf.Abs(Mathf.Sin(T));
}
#endregion
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1b2d465af9aac7e449a0e3341aca43e5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,139 @@
/**
* 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 UnityEngine;
namespace Live2D.Cubism.Framework.MouthMovement
{
/// <summary>
/// Controls <see cref="CubismMouthParameter"/>s.
/// </summary>
public sealed class CubismMouthController : MonoBehaviour, ICubismUpdatable
{
/// <summary>
/// The blend mode.
/// </summary>
[SerializeField]
public CubismParameterBlendMode BlendMode = CubismParameterBlendMode.Multiply;
/// <summary>
/// The opening of the mouth.
/// </summary>
[SerializeField, Range(0f, 1f)]
public float MouthOpening = 1f;
/// <summary>
/// Mouth parameters.
/// </summary>
private CubismParameter[] Destinations { get; set; }
/// <summary>
/// Model has update controller component.
/// </summary>
[HideInInspector]
public bool HasUpdateController { get; set; }
/// <summary>
/// Refreshes controller. Call this method after adding and/or removing <see cref="CubismMouthParameter"/>s.
/// </summary>
public void Refresh()
{
var model = this.FindCubismModel();
// Fail silently...
if (model == null)
{
return;
}
// Cache destinations.
var tags = model
.Parameters
.GetComponentsMany<CubismMouthParameter>();
Destinations = new CubismParameter[tags.Length];
for (var i = 0; i < tags.Length; ++i)
{
Destinations[i] = tags[i].GetComponent<CubismParameter>();
}
// Get cubism update controller.
HasUpdateController = (GetComponent<CubismUpdateController>() != null);
}
/// <summary>
/// Called by cubism update controller. Order to invoke OnLateUpdate.
/// </summary>
public int ExecutionOrder
{
get { return CubismUpdateExecutionOrder.CubismMouthController; }
}
/// <summary>
/// Called by cubism update controller. Needs to invoke OnLateUpdate on Editing.
/// </summary>
public bool NeedsUpdateOnEditing
{
get { return false; }
}
/// <summary>
/// Called by cubism update controller. Updates controller.
/// </summary>
/// <remarks>
/// Make sure this method is called after any animations are evaluated.
/// </remarks>
public void OnLateUpdate()
{
// Fail silently.
if (!enabled || Destinations == null)
{
return;
}
// Apply value.
Destinations.BlendToValue(BlendMode, MouthOpening);
}
#region Unity Events Handling
/// <summary>
/// Called by Unity. Makes sure cache is initialized.
/// </summary>
private void Start()
{
// Initialize cache.
Refresh();
}
/// <summary>
/// Called by Unity.
/// </summary>
private void LateUpdate()
{
if(!HasUpdateController)
{
OnLateUpdate();
}
}
#endregion
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: adeec4ed250bae44d8777078a3ec1e00
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,20 @@
/**
* 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 UnityEngine;
namespace Live2D.Cubism.Framework.MouthMovement
{
/// <summary>
/// Tagging component for mouth parameters.
/// </summary>
public sealed class CubismMouthParameter : MonoBehaviour
{
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7198ae67c7f9bd14b86134e395d11f86
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: