LookAt

업데이트: 2020/01/30

개요

LookAt은 임의의 파라미터를 특정 좌표를 따르도록 값을 조작하는 기능입니다.
추종시키는 좌표를 유저 측에서 커스터마이즈 하면, Cubism의 모델을 특정 GameObject 등에 추종시키는 것이 가능합니다.
LookAt 사용 방법은 여기를 참조하십시오. 

Cubism SDK for Unity의 LookAt은 세 가지 요소로 구성됩니다.

  1. 추종시킬 파라미터 지정용 컴포넌트
  2. 각 파라미터에 값을 적용하는 컴포넌트
  3. 2에서 적용하는 값 조작

1. 추종시킬 파라미터 지정용 컴포넌트

LookAt에서 추종시킬 파라미터를 지정하려면 CubismLookParameter를 사용합니다.

CubismLookParameter는 [Prefab 루트] /Parameters/ 아래에 배치된 GameObject에 연결하여 사용합니다.
이것이 연결된 GameObject와 동일한 ID의 파라미터를 시선 추종용 파라미터로 취급합니다.

CubismLookParameter에는 Axis, Factor의 두 가지 설정 항목이 있습니다.

        /// <summary>
        /// Look axis.
        /// </summary>
        [SerializeField]
        public CubismLookAxis Axis;


        /// <summary>
        /// Factor.
        /// </summary>
        [SerializeField]
        public float Factor;
  • Axis

입력된 좌표의 어느 축의 값을 사용할지를 설정합니다.
설정할 수 있는 항목은 X, Y, Z의 3개입니다.

namespace Live2D.Cubism.Framework.LookAt
{
    /// <summary>
    /// Look axis.
    /// </summary>
    public enum CubismLookAxis
    {
        /// <summary>
        /// X axis.
        /// </summary>
        X,

        /// <summary>
        /// Y axis.
        /// </summary>
        Y,

        /// <summary>
        /// Z axis.
        /// </summary>
        Z
    }
}
  • Factor

적용되는 값에 대한 보정값을 설정합니다.
입력되는 좌표는 적용 시 -1.0f에서 1.0f의 범위로 가공된 값입니다.
Factor에 설정하는 값은 입력된 값을 각 파라미터의 최솟값과 최댓값에 맞게 곱하는 배율입니다.

        /// <summary>
        /// Updates and evaluates the instance.
        /// </summary>
        /// <param name="targetOffset">Delta to target.</param>
        /// <returns>Evaluation result.</returns>
        internal float TickAndEvaluate(Vector3 targetOffset)
        {
            var result = (Axis == CubismLookAxis.X)
                ? targetOffset.x
                : targetOffset.y;


            if (Axis == CubismLookAxis.Z)
            {
                result = targetOffset.z;
            }


            return result * Factor;
        }

또한 CubismLookParameter는 CubismLookController가 참조 대상을 취득하기 위한 마커로도 사용합니다.

2. 각 파라미터에 값을 적용하는 컴포넌트

각 파라미터에 시선 추적을 적용하려면 CubismLookController를 사용합니다.
CubismLookController를 사용할 때는 Cubism의 Prefab 루트에 연결합니다.

CubismLookController를 초기화할 때 Prefab에 연결된 모든 CubismLookParameter의 참조를 취득합니다.
실행 중에 시선 추종용 파라미터를 추가/삭제했을 때에는 CubismLookController.Refresh()를 호출해 참조를 다시 취득합니다.

        /// <summary>
        /// Refreshes the controller. Call this method after adding and/or removing <see cref="CubismLookParameter"/>s.
        /// </summary>
        public void Refresh()
        {
            var model = this.FindCubismModel();


            // Catch sources and destinations.
            Sources = model
                .Parameters
                .GetComponentsMany<CubismLookParameter>();
            Destinations = new CubismParameter[Sources.Length];


            for (var i = 0; i < Sources.Length; ++i)
            {
                Destinations[i] = Sources[i].GetComponent<CubismParameter>();
            }

            // Get cubism update controller.
            HasUpdateController = (GetComponent<CubismUpdateController>() != null);
        }

        ...
        
        /// <summary>
        /// Called by Unity. Makes sure cache is initialized.
        /// </summary>
        private void Start()
        {
            // Default center if necessary.
            if (Center == null)
            {
                Center = transform;
            }


            // Initialize cache.
            Refresh();
        }

CubismLookController는 매 프레임의 LateUpdate() 타이밍에 CubismLookParameter로 마킹된 파라미터에 대해 CubismLookController.Target에 설정한 오브젝트가 반환하는 좌표를 적용합니다.

            // Update position.
            var position = LastPosition;
            GoalPosition = transform.InverseTransformPoint(target.GetPosition()) - Center.localPosition;


            if (position != GoalPosition)
            {
                position = Vector3.SmoothDamp(
                    position,
                    GoalPosition,
                    ref VelocityBuffer,
                    Damping);
            }


            // Update sources and destinations.
            for (var i = 0; i < Destinations.Length; ++i)
            {
                Destinations[i].BlendToValue(BlendMode, Sources[i].TickAndEvaluate(position));
            }


            // Store position.
            LastPosition = position;

3. 2에서 적용하는 값의 조작

「2. 각 파라미터에 값을 적용하는 컴포넌트」에서 설명한 대로, CubismLookController가 시선추종용의 파라미터에 적용하는 좌표는 CubismLookController.Target에 설정한 오브젝트가 반환합니다.

이것은 ICubismLookTarget 인터페이스를 구현한 것으로, 유저 측에서 이를 구현하시면 모델을 임의의 좌표에 추종시킬 수 있습니다.

using UnityEngine;


namespace Live2D.Cubism.Framework.LookAt
{
    /// <summary>
    /// Target to look at.
    /// </summary>
    public interface ICubismLookTarget
    {
        /// <summary>
        /// Gets the position of the target.
        /// </summary>
        /// <returns>The position of the target in world space.</returns>
        Vector3 GetPosition();


        /// <summary>
        /// Gets whether the target is active.
        /// </summary>
        /// <returns><see langword="true"/> if the target is active; <see langword="false"/> otherwise.</returns>
        bool IsActive();
    }
}
  • GetPosition()

추종하는 좌표를 반환합니다.
여기서 반환하는 좌표는 월드 좌표로 취급됩니다.

  • IsActive()

추종의 유효 여부를 반환합니다.
true가 반환되고 있을 때만 추종합니다.

SDK에는 ICubismLookTarget을 구현한 예로 CubismLookTargetBehaviour가 포함되어 있습니다.
CubismLookTargetBehaviour는 그것이 연결된 GameObject의 좌표를 반환하는 샘플입니다.

using UnityEngine;


namespace Live2D.Cubism.Framework.LookAt
{
    /// <summary>
    /// Straight-forward <see cref="ICubismLookTarget"/> <see cref="MonoBehaviour"/>.
    /// </summary>
    public class CubismLookTargetBehaviour : MonoBehaviour, ICubismLookTarget
    {
        #region Implementation of ICubismLookTarget

        /// <summary>
        /// Gets the position of the target.
        /// </summary>
        /// <returns>The position of the target in world space.</returns>
        Vector3 ICubismLookTarget.GetPosition()
        {
            return transform.position;
        }

        /// <summary>
        /// Gets whether the target is active.
        /// </summary>
        /// <returns><see langword="true"/> if the target is active; <see langword="false"/> otherwise.</returns>
        bool ICubismLookTarget.IsActive()
        {
            return isActiveAndEnabled;
        }

        #endregion
    }
}
이 기사가 도움이 되었나요?
아니요
이 기사에 관한 의견 및 요청사항을 보내 주시기 바랍니다.