【UnityC#講座】ユニティちゃんにボイスをつける【AudioSource】

ユニティちゃんボイス/トップ

Unity2019.2.2f1
Windows10

ユニティちゃんボイス/トップ

【UnityC#講座】3D人型モデルを三人称視点で動かす操作を改良

【UnityC#講座】ユニティちゃんにパンチさせる

【UnityC#講座】ユニティちゃんに殴り合いをさせる【NavMeshAgent】

またこれらの記事の続きです。

今回はユニティちゃんアセットに入っているボイスを使ってみます。
攻撃とダメージを受ける時に声が出るようにしました。

完成したのがこの動画です。

■SEオブジェクトとSEスクリプトを作る

まず空のオブジェクトを出しSEと名付けます。
SEはSound Effectの略でボイスを扱うにはふさわしくないかもしれませんが、ボイスとSEのUnity上での扱いは変わらないので良しとしましょう。

次にSEスクリプトを作ります。
C#ファイルの名前をこちらもSEにしてください。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//オブジェクトにAudioSourceコンポーネントを追加
[RequireComponent(typeof(AudioSource))]
public class SE : MonoBehaviour
{
//音声ファイルを入れる
public AudioClip[] sound;
//AudioSourceコンポーネントを入れる変数
AudioSource audioSource;
void Start()
{
//AudioSourceコンポーネントを取得
audioSource = GetComponent<AudioSource>();
}
public void AttackSound()
{
//音声を鳴らす
audioSource.PlayOneShot(sound[0]);
}
public void DamageSound()
{
audioSource.PlayOneShot(sound[1]);
}
}
view raw 47.cs hosted with ❤ by GitHub

AudioSourceコンポーネントを追加・取得し、PlayOneShot()で鳴らします。
攻撃時にはAttackSound()メソッドを、ダメージ時にはDamageSound()メソッドを他のスクリプトから呼び出します。
Player、Opponentスクリプトに直接書いても良いのですが、手間を減らすためにこうしました。

続いて、SEスクリプトをSEオブジェクトにアタッチしたらInspectorから設定をします。
Soundに2と入れてインター押すと空欄が2つでき、そこに使う音声を入れます。

ユニティちゃんボイス/SEスクリプト/Inspectorから設定

Element 0にuniv0001を、Element 1にuniv0012を入れてください。
ボイスの在り処はこちらです。

Project > Assets > unity-chan! > unity-chan!Model > Audio > Voice

■Player、Opponentスクリプトに追加する

次はPlayer、OpponentスクリプトにSEを呼び出す記述を追加します。
変数を宣言し、Start()でオブジェクトとスクリプトを取得、そして後は攻撃、ダメージ時に一度だけ呼び出される部分からSEスクリプトのメソッドを呼び出してやるだけで完成です。
Action.AttackとAction.Damageの時に呼ぶ条件にすると音声が連続して出てしまうので注意してください。

Player.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(CapsuleCollider))]
[RequireComponent(typeof(Rigidbody))]
public class Player : MonoBehaviour
{
[SerializeField] float speed = 4f;
private Animator animator;
Transform cam;
Rigidbody rb;
CapsuleCollider caps;
enum Action
{
Move,
Attack,
Damage
}
[SerializeField] Action action = Action.Move;
[SerializeField]GameObject attackObj;
//SEオブジェクトを入れる
GameObject seObj;
//SEスクリプトを入れる
SE seScr;
void Start()
{
animator = GetComponent<Animator>();
rb = GetComponent<Rigidbody>();
rb.constraints = RigidbodyConstraints.FreezeRotation;
cam = Camera.main.transform;
caps = GetComponent<CapsuleCollider>();
caps.center = new Vector3(0, 0.76f, 0);
caps.radius = 0.23f;
caps.height = 1.6f;
attackObj.SetActive(false);
//SEオブジェクトを取得
seObj = GameObject.Find("SE");
//SEスクリプトを取得
seScr = seObj.GetComponent<SE>();
}
void Update()
{
if (action == Action.Move)
{
float x = Input.GetAxisRaw("Horizontal") * Time.deltaTime * speed;
float z = Input.GetAxisRaw("Vertical") * Time.deltaTime * speed;
animator.SetFloat("X", x * 50);
animator.SetFloat("Y", z * 50);
if (z > 0)
{
transform.rotation = Quaternion.Euler(new Vector3(transform.rotation.x,
cam.eulerAngles.y, transform.rotation.z));
}
else if (z < 0)
{
z = z / 1.5f;
}
transform.position += transform.forward * z + transform.right * x;
if (Input.GetMouseButtonDown(0))
{
action = Action.Attack;
//SEスクリプトのAttackSound()を呼ぶ
seScr.AttackSound();
}
}
else if (action == Action.Attack)
{
animator.SetBool("Attack", true);
attackObj.SetActive(true);
}
else if (action == Action.Damage)
{
animator.SetBool("Damage", true);
}
}
private void OnTriggerEnter(Collider other)
{
if (other.gameObject.tag == "EnemyAttack")
{
if (action == Action.Damage)
{
return;
}
else
{
action = Action.Damage;
//SEスクリプトのDamageSound()を呼ぶ
seScr.DamageSound();
}
}
}
public void AttackEnd()
{
Invoke("AttackEndAnim", 0.5f);
}
void AttackEndAnim()
{
action = Action.Move;
animator.SetBool("Attack", false);
attackObj.SetActive(false);
}
void DamageEnd()
{
action = Action.Move;
animator.SetBool("Damage", false);
}
}
view raw 47a.cs hosted with ❤ by GitHub

スポンサーリンク

Opponent.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
[RequireComponent(typeof(CapsuleCollider))]
[RequireComponent(typeof(Rigidbody))]
[RequireComponent(typeof(NavMeshAgent))]
public class Opponent : MonoBehaviour
{
private NavMeshAgent agent;
private Vector3 startPoint;
Rigidbody rb;
CapsuleCollider caps;
private Animator animator;
GameObject player;
[SerializeField] float time;
[SerializeField] float chaseTime = 5.0f;
[SerializeField] float attackTime = 0.5f;
[SerializeField] float chaseSpeed = 3.5f;
[SerializeField] float returnSpeed = 1.0f;
enum Action
{
Wait,
Attack,
Chase,
Damage,
Return
}
[SerializeField] Action action = Action.Wait;
public GameObject attackJudgment;
//SEオブジェクトを入れる
GameObject seObj;
//SEスクリプトを入れる
SE seScr;
void Start()
{
animator = GetComponent<Animator>();
rb = GetComponent<Rigidbody>();
rb.constraints = RigidbodyConstraints.FreezeRotation;
caps = GetComponent<CapsuleCollider>();
caps.center = new Vector3(0, 0.8f, 0);
caps.radius = 0.23f;
caps.height = 1.6f;
agent = GetComponent<NavMeshAgent>();
agent.autoBraking = false;
startPoint = transform.position;
player = GameObject.FindGameObjectWithTag("Player");
attackJudgment.SetActive(false);
//SEオブジェクトを取得
seObj = GameObject.Find("SE");
//SEスクリプトを取得
seScr = seObj.GetComponent<SE>();
}
void Update()
{
if (action == Action.Wait)
{
agent.isStopped = true;
animator.SetFloat("Y", agent.velocity.sqrMagnitude);
}
else if (action == Action.Chase)
{
agent.isStopped = false;
agent.destination = player.transform.position;
agent.speed = chaseSpeed;
animator.SetFloat("Y", agent.velocity.sqrMagnitude);
time += Time.deltaTime;
if (time > chaseTime)
{
action = Action.Return;
time = 0;
}
}
else if (action == Action.Attack)
{
animator.SetBool("Attack", true);
agent.speed = 0;
attackJudgment.SetActive(true);
}
else if (action == Action.Damage)
{
animator.SetBool("Damage", true);
agent.speed = 0;
}
else if (action == Action.Return)
{
animator.SetFloat("Y", agent.velocity.sqrMagnitude);
agent.speed = returnSpeed;
agent.destination = startPoint;
if (!agent.pathPending && agent.remainingDistance < 0.1f)
{
action = Action.Wait;
}
}
}
private void OnTriggerEnter(Collider other)
{
if (other.gameObject.tag == "PlayerAttack")
{
if (action == Action.Damage)
{
return;
}
else
{
action = Action.Damage;
//SEスクリプトのDamageSound()を呼ぶ
seScr.DamageSound();
}
}
}
private void OnCollisionEnter(UnityEngine.Collision collision)
{
if (collision.gameObject.tag == "Player" && action == Action.Chase)
{
action = Action.Attack;
//SEスクリプトのAttackSound()を呼ぶ
seScr.AttackSound();
}
}
void DamageEnd()
{
animator.SetBool("Damage", false);
action = Action.Chase;
}
void AttackEnd()
{
Invoke("AttackEndAnim", attackTime);
}
void AttackEndAnim()
{
animator.SetBool("Attack", false);
attackJudgment.SetActive(false);
action = Action.Chase;
}
}
view raw 47b.cs hosted with ❤ by GitHub

これでボイスが出るようになったはずですがちゃんと出たでしょうか?
今回はこれで終わりです。

■関連記事

【UnityC#講座】ユニティちゃんをスカイリム風に操作する

フリーゲーム「一人称で生成迷路脱出」を公開しました

ユニティちゃんライセンス

この作品はユニティちゃんライセンス条項の元に提供されています

スポンサーリンク

目次に戻る