1, Playerプレハブの手の部分にEquippedSwordを作成する
2, EquippedSwordに武器を子オブジェクト化し、再生した状態でScaleや位置を調整してコピーしておく
3, コピーした位置をPlayerのTransformにPasteする
4, Waeponsフォルダを作成し、プレハブ化する。(プレハブ済のものは削除しておく)
5, Fighterに下記コードを追加する
using UnityEngine;
using RPG.Movement;
using RPG.Core;
using System;
namespace RPG.Combat
{
public class Fighter : MonoBehaviour, IAction
{
[SerializeField] float weaponRange = 2f;
[SerializeField] float timeBetweenAttacks = 1f;
[SerializeField] float weaponDamage = 5f;
[SerializeField] GameObject weaponPrefab = null; //追加
[SerializeField] Transform handTransform = null; //追加
Health target;
float timeSinceLastAttack = Mathf.Infinity;
//追加
private void Start()
{
SpawnWeapon();
}
private void Update()
{
timeSinceLastAttack += Time.deltaTime;
if (target == null) return;
if (target.IsDead()) return;
if (!GetIsInRange())
{
GetComponent<Mover>().MoveTo(target.transform.position, 1f);
}
else
{
GetComponent<Mover>().Cancel();
AttackBehaviour();
}
}
//追加
private void SpawnWeapon()
{
Instantiate(weaponPrefab, handTransform);
}
private void AttackBehaviour()
{
transform.LookAt(target.transform);
if (timeSinceLastAttack > timeBetweenAttacks)
{
TriggerAttack();
timeSinceLastAttack = 0;
}
}
private void TriggerAttack()
{
GetComponent<Animator>().ResetTrigger("stopAttack");
GetComponent<Animator>().SetTrigger("attack");
}
void Hit()
{
if(target == null) { return; }
target.TakeDamage(weaponDamage);
}
private bool GetIsInRange()
{
return Vector3.Distance(transform.position, target.transform.position) < weaponRange;
}
public bool CanAttack(GameObject combatTarget)
{
if (combatTarget == null) { return false; }
Health targetToTest = combatTarget.GetComponent<Health>();
return targetToTest != null && !targetToTest.IsDead();
}
public void Attack(GameObject combatTarget)
{
GetComponent<ActionScheduler>().StartAction(this);
target = combatTarget.GetComponent<Health>();
}
public void Cancel()
{
StopAttack();
target = null;
GetComponent<Mover>().Cancel();
}
private void StopAttack()
{
GetComponent<Animator>().ResetTrigger("attack");
GetComponent<Animator>().SetTrigger("stopAttack");
}
}
}
アニメーションの実装
1, Swordフォルダを作成し、EquippedSwordを入れる
2, SwordフォルダにAnimatorOverrideControllerを作成する
3, SwordOverrideControllerに名前を変更し、CharactorControllerを設定する
4, SwordOverrideControllerのUnarmed-Attakに任意のアニメーションを設定する
5, Fighterに下記スクリプトを書く
using UnityEngine;
using RPG.Movement;
using RPG.Core;
using System;
namespace RPG.Combat
{
public class Fighter : MonoBehaviour, IAction
{
[SerializeField] float weaponRange = 2f;
[SerializeField] float timeBetweenAttacks = 1f;
[SerializeField] float weaponDamage = 5f;
[SerializeField] GameObject weaponPrefab = null;
[SerializeField] Transform handTransform = null;
[SerializeField] AnimatorOverrideController weaponOverride = null; //追加
Health target;
float timeSinceLastAttack = Mathf.Infinity;
private void Start()
{
SpawnWeapon();
}
private void Update()
{
timeSinceLastAttack += Time.deltaTime;
if (target == null) return;
if (target.IsDead()) return;
if (!GetIsInRange())
{
GetComponent<Mover>().MoveTo(target.transform.position, 1f);
}
else
{
GetComponent<Mover>().Cancel();
AttackBehaviour();
}
}
private void SpawnWeapon()
{
Instantiate(weaponPrefab, handTransform);
Animator animator = GetComponent<Animator>(); //追加
animator.runtimeAnimatorController = weaponOverride; //追加
}
private void AttackBehaviour()
{
transform.LookAt(target.transform);
if (timeSinceLastAttack > timeBetweenAttacks)
{
TriggerAttack();
timeSinceLastAttack = 0;
}
}
private void TriggerAttack()
{
GetComponent<Animator>().ResetTrigger("stopAttack");
GetComponent<Animator>().SetTrigger("attack");
}
void Hit()
{
if(target == null) { return; }
target.TakeDamage(weaponDamage);
}
private bool GetIsInRange()
{
return Vector3.Distance(transform.position, target.transform.position) < weaponRange;
}
public bool CanAttack(GameObject combatTarget)
{
if (combatTarget == null) { return false; }
Health targetToTest = combatTarget.GetComponent<Health>();
return targetToTest != null && !targetToTest.IsDead();
}
public void Attack(GameObject combatTarget)
{
GetComponent<ActionScheduler>().StartAction(this);
target = combatTarget.GetComponent<Health>();
}
public void Cancel()
{
StopAttack();
target = null;
GetComponent<Mover>().Cancel();
}
private void StopAttack()
{
GetComponent<Animator>().ResetTrigger("attack");
GetComponent<Animator>().SetTrigger("stopAttack");
}
}
}
6,PlayerプレハブのWeaponOverrideにSwordOverrideControllerをアタッチする
スクリプト化可能なオブジェクトの作成
1, Wwaponスクリプトを作成し、各スクリプトに下記コードを書く
using UnityEngine;
namespace RPG.Combat
{
[CreateAssetMenu(fileName = "Weapon", menuName = "Weapons/Make New Weapon", order = 0)]
public class Weapon : ScriptableObject
{
[SerializeField] AnimatorOverrideController animatorOverride = null;
[SerializeField] GameObject weaponPrefab = null;
public void Spawn(Transform handTransform, Animator animator)
{
Instantiate(weaponPrefab, handTransform);
animator.runtimeAnimatorController = animatorOverride;
}
}
}
using UnityEngine;
using RPG.Movement;
using RPG.Core;
using System;
namespace RPG.Combat
{
public class Fighter : MonoBehaviour, IAction
{
[SerializeField] float weaponRange = 2f;
[SerializeField] float timeBetweenAttacks = 1f;
[SerializeField] float weaponDamage = 5f;
[SerializeField] Transform handTransform = null;
[SerializeField] Weapon weapon = null; //追加
Health target;
float timeSinceLastAttack = Mathf.Infinity;
private void Start()
{
SpawnWeapon();
}
private void Update()
{
timeSinceLastAttack += Time.deltaTime;
if (target == null) return;
if (target.IsDead()) return;
if (!GetIsInRange())
{
GetComponent<Mover>().MoveTo(target.transform.position, 1f);
}
else
{
GetComponent<Mover>().Cancel();
AttackBehaviour();
}
}
private void SpawnWeapon()
{
if (weapon == null) return; //追加
Animator animator = GetComponent<Animator>();
weapon.Spawn(handTransform, animator); //追加
}
private void AttackBehaviour()
{
transform.LookAt(target.transform);
if (timeSinceLastAttack > timeBetweenAttacks)
{
TriggerAttack();
timeSinceLastAttack = 0;
}
}
private void TriggerAttack()
{
GetComponent<Animator>().ResetTrigger("stopAttack");
GetComponent<Animator>().SetTrigger("attack");
}
void Hit()
{
if(target == null) { return; }
target.TakeDamage(weaponDamage);
}
private bool GetIsInRange()
{
return Vector3.Distance(transform.position, target.transform.position) < weaponRange;
}
public bool CanAttack(GameObject combatTarget)
{
if (combatTarget == null) { return false; }
Health targetToTest = combatTarget.GetComponent<Health>();
return targetToTest != null && !targetToTest.IsDead();
}
public void Attack(GameObject combatTarget)
{
GetComponent<ActionScheduler>().StartAction(this);
target = combatTarget.GetComponent<Health>();
}
public void Cancel()
{
StopAttack();
target = null;
GetComponent<Mover>().Cancel();
}
private void StopAttack()
{
GetComponent<Animator>().ResetTrigger("attack");
GetComponent<Animator>().SetTrigger("stopAttack");
}
}
}
2, Swordフォルダ内にCreate→Weapons→MakeNewWeaponsを押してSwordを作成する
3, SwordにSwordOverrideControllerとEquippedSwordを設定する
4, PlayerプレハブのWeaponにSwordをアタッチする
武器無し攻撃の実装
1, Weaponsフォルダ内にUnarmedフォルダを作成し、Create→Weapons→MakeNewWeaponでUnarmedを作成。
2, 各スクリプトに下記コードを書く
using UnityEngine;
namespace RPG.Combat
{
[CreateAssetMenu(fileName = "Weapon", menuName = "Weapons/Make New Weapon", order = 0)]
public class Weapon : ScriptableObject
{
[SerializeField] AnimatorOverrideController animatorOverride = null;
[SerializeField] GameObject equippedPrefab = null;
[SerializeField] float weaponDamage = 5f; //Fighter.csから移動
[SerializeField] float weaponRange = 2f; //Fighter.csから移動
public void Spawn(Transform handTransform, Animator animator)
{
if (equippedPrefab != null)
{
Instantiate(equippedPrefab, handTransform);
}
if (animatorOverride != null)
{
animator.runtimeAnimatorController = animatorOverride;
}
}
public float GetDamage()
{
return weaponDamage;
}
public float GetRange()
{
return weaponRange;
}
}
}
void Hit()
{
if(target == null) { return; }
target.TakeDamage(weapon.GetDamage()); //GetDamageに変更
}
private bool GetIsInRange()
{
return Vector3.Distance(transform.position, target.transform.position) < weapon.GetRange(); //GetRangeに変更
}
4, SWordのEquippedPrefabにEquippedSwordオブジェクトを設定する
武器を拾う
1, プロジェクトにPickupsフォルダを作成。ヒエラルキーにPickupsとSwordPickupのげーむオブジェクトを作成し、SwordPickupをプレハブ化する。
3, SwordPickupにSphereColliderを付け、Colliderのサイズを調整する
4, WeaponPickupスクリプトを作成し、SwordPickupに付ける
5, 下記スクリプトを記述する
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace RPG.Combat
{
public class WeaponPickup : MonoBehaviour
{
[SerializeField] Weapon weapon = null;
private void OnTriggerEnter(Collider other)
{
if (other.gameObject.tag == "Player")
{
other.GetComponent<Fighter>().EquipWeapon(weapon);
Destroy(gameObject);
}
}
}
}
using UnityEngine;
using RPG.Movement;
using RPG.Core;
using System;
namespace RPG.Combat
{
public class Fighter : MonoBehaviour, IAction
{
[SerializeField] float timeBetweenAttacks = 1f;
[SerializeField] Transform handTransform = null;
[SerializeField] Weapon defaultWeapon = null; //変更
Health target;
float timeSinceLastAttack = Mathf.Infinity;
Weapon currentWeapon = null; //追加
private void Start()
{
EquipWeapon(defaultWeapon); //追加
}
private void Update()
{
timeSinceLastAttack += Time.deltaTime;
if (target == null) return;
if (target.IsDead()) return;
if (!GetIsInRange())
{
GetComponent<Mover>().MoveTo(target.transform.position, 1f);
}
else
{
GetComponent<Mover>().Cancel();
AttackBehaviour();
}
}
public void EquipWeapon(Weapon weapon) //EquipWeaponに変更
{
currentWeapon = weapon; //追加
Animator animator = GetComponent<Animator>();
weapon.Spawn(handTransform, animator);
}
private void AttackBehaviour()
{
transform.LookAt(target.transform);
if (timeSinceLastAttack > timeBetweenAttacks)
{
TriggerAttack();
timeSinceLastAttack = 0;
}
}
private void TriggerAttack()
{
GetComponent<Animator>().ResetTrigger("stopAttack");
GetComponent<Animator>().SetTrigger("attack");
}
void Hit()
{
if(target == null) { return; }
target.TakeDamage(currentWeapon.GetDamage()); //currentWeaponに変更
}
private bool GetIsInRange()
{
return Vector3.Distance(transform.position, target.transform.position) < currentWeapon.GetRange(); //currentWeaponに変更
}
public bool CanAttack(GameObject combatTarget)
{
if (combatTarget == null) { return false; }
Health targetToTest = combatTarget.GetComponent<Health>();
return targetToTest != null && !targetToTest.IsDead();
}
public void Attack(GameObject combatTarget)
{
GetComponent<ActionScheduler>().StartAction(this);
target = combatTarget.GetComponent<Health>();
}
public void Cancel()
{
StopAttack();
target = null;
GetComponent<Mover>().Cancel();
}
private void StopAttack()
{
GetComponent<Animator>().ResetTrigger("attack");
GetComponent<Animator>().SetTrigger("stopAttack");
}
}
}
6, SwordPickupのWeaponにSwordをアタッチし、IsTriggerにチェックを入れる
7, PlayerプレハブのFighterスクリプト→DefaultWeaponにUnarmedをアタッチする
上記で再生したところplayerがプルプルしていたので追加でIsKinematicにチェックを入れました。
左手に持つ武器を実装
2, 各スクリプトに下記コードを記述する
using UnityEngine;
namespace RPG.Combat
{
[CreateAssetMenu(fileName = "Weapon", menuName = "Weapons/Make New Weapon", order = 0)]
public class Weapon : ScriptableObject
{
[SerializeField] AnimatorOverrideController animatorOverride = null;
[SerializeField] GameObject equippedPrefab = null;
[SerializeField] float weaponDamage = 5f;
[SerializeField] float weaponRange = 2f;
[SerializeField] bool isRightHanded = true; //追加
public void Spawn(Transform rightHand, Transform leftHand, Animator animator) //追加
{
if (equippedPrefab != null)
{
Transform handTransform; //追加
if (isRightHanded) handTransform = rightHand; //追加
else handTransform = leftHand; //追加
Instantiate(equippedPrefab, handTransform);
}
if (animatorOverride != null)
{
animator.runtimeAnimatorController = animatorOverride;
}
}
public float GetDamage()
{
return weaponDamage;
}
public float GetRange()
{
return weaponRange;
}
}
}
using UnityEngine;
using RPG.Movement;
using RPG.Core;
using System;
namespace RPG.Combat
{
public class Fighter : MonoBehaviour, IAction
{
[SerializeField] float timeBetweenAttacks = 1f;
[SerializeField] Transform rightHandTransform = null; //変更
[SerializeField] Transform leftHandTransform = null; //追加
[SerializeField] Weapon defaultWeapon = null;
Health target;
float timeSinceLastAttack = Mathf.Infinity;
Weapon currentWeapon = null;
private void Start()
{
EquipWeapon(defaultWeapon);
}
private void Update()
{
timeSinceLastAttack += Time.deltaTime;
if (target == null) return;
if (target.IsDead()) return;
if (!GetIsInRange())
{
GetComponent<Mover>().MoveTo(target.transform.position, 1f);
}
else
{
GetComponent<Mover>().Cancel();
AttackBehaviour();
}
}
public void EquipWeapon(Weapon weapon)
{
currentWeapon = weapon;
Animator animator = GetComponent<Animator>();
weapon.Spawn(rightHandTransform, leftHandTransform, animator); //追加
}
private void AttackBehaviour()
{
transform.LookAt(target.transform);
if (timeSinceLastAttack > timeBetweenAttacks)
{
TriggerAttack();
timeSinceLastAttack = 0;
}
}
private void TriggerAttack()
{
GetComponent<Animator>().ResetTrigger("stopAttack");
GetComponent<Animator>().SetTrigger("attack");
}
void Hit()
{
if(target == null) { return; }
target.TakeDamage(currentWeapon.GetDamage());
}
private bool GetIsInRange()
{
return Vector3.Distance(transform.position, target.transform.position) < currentWeapon.GetRange();
}
public bool CanAttack(GameObject combatTarget)
{
if (combatTarget == null) { return false; }
Health targetToTest = combatTarget.GetComponent<Health>();
return targetToTest != null && !targetToTest.IsDead();
}
public void Attack(GameObject combatTarget)
{
GetComponent<ActionScheduler>().StartAction(this);
target = combatTarget.GetComponent<Health>();
}
public void Cancel()
{
StopAttack();
target = null;
GetComponent<Mover>().Cancel();
}
private void StopAttack()
{
GetComponent<Animator>().ResetTrigger("attack");
GetComponent<Animator>().SetTrigger("stopAttack");
}
}
}
3, PlayerのHandLとHandRをFighterコンポーネントにアタッチする
4, SwordのIsRightHandedのチェックを外す
6, BowフォルダにMakeNewWeaponとAnimatorOverrideControllerを作成する
7,BowAnimatorOverrideにCharactorとアニメーションをアタッチする
8, BowのAnimatorOverrideとdamage値など設定する
9, PlayerのHandLにBowオブジェクトを作成し、武器を子オブジェクト化しておく。それをプレハブ化する
10,再生しながら武器の位置を合わせてTransformをコピーする
12, PlayerのdefaltWeaponをBowにする
矢をplayerに当てる
2, ProjectにProjectileフォルダを作成。ヒエラルキーにArrowProjectileオブジェクトを作成し、プレハブ化する
3, ArrowProjectileに矢のプレハブを子オブジェクト化する
6, 下記のコードを記述する
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Projectile : MonoBehaviour
{
[SerializeField] Transform target = null;
[SerializeField] float speed = 1;
void Update()
{
if (target == null) return;
transform.LookAt(GetAimLocation());
transform.Translate(Vector3.forward * speed * Time.deltaTime);
}
private Vector3 GetAimLocation()
{
CapsuleCollider targetCapsule = target.GetComponent<CapsuleCollider>();
if (targetCapsule == null)
{
return target.position;
}
return target.position + Vector3.up * targetCapsule.height / 2;
}
}
7, ArrowProjectileのTargetにplayerをアタッチする
矢を敵に飛ばす
1, アタックアニメーションを確認し、Hitなどのイベントがついているか確認する
2, 各スクリプトに下記コードを追加する
using UnityEngine;
using RPG.Movement;
using RPG.Core;
using System;
namespace RPG.Combat
{
public class Fighter : MonoBehaviour, IAction
{
[SerializeField] float timeBetweenAttacks = 1f;
[SerializeField] Transform rightHandTransform = null; //変更
[SerializeField] Transform leftHandTransform = null; //追加
[SerializeField] Weapon defaultWeapon = null;
Health target;
float timeSinceLastAttack = Mathf.Infinity;
Weapon currentWeapon = null;
private void Start()
{
EquipWeapon(defaultWeapon);
}
private void Update()
{
timeSinceLastAttack += Time.deltaTime;
if (target == null) return;
if (target.IsDead()) return;
if (!GetIsInRange())
{
GetComponent<Mover>().MoveTo(target.transform.position, 1f);
}
else
{
GetComponent<Mover>().Cancel();
AttackBehaviour();
}
}
public void EquipWeapon(Weapon weapon)
{
currentWeapon = weapon;
Animator animator = GetComponent<Animator>();
weapon.Spawn(rightHandTransform, leftHandTransform, animator); //追加
}
private void AttackBehaviour()
{
transform.LookAt(target.transform);
if (timeSinceLastAttack > timeBetweenAttacks)
{
TriggerAttack();
timeSinceLastAttack = 0;
}
}
private void TriggerAttack()
{
GetComponent<Animator>().ResetTrigger("stopAttack");
GetComponent<Animator>().SetTrigger("attack");
}
void Hit()
{
if(target == null) { return; }
if (currentWeapon.HasProjectile())
{
currentWeapon.LaunchProjectile(rightHandTransform, leftHandTransform, target);
}
else
{
target.TakeDamage(currentWeapon.GetDamage());
}
}
void Shoot()
{
Hit();
}
private bool GetIsInRange()
{
return Vector3.Distance(transform.position, target.transform.position) < currentWeapon.GetRange();
}
public bool CanAttack(GameObject combatTarget)
{
if (combatTarget == null) { return false; }
Health targetToTest = combatTarget.GetComponent<Health>();
return targetToTest != null && !targetToTest.IsDead();
}
public void Attack(GameObject combatTarget)
{
GetComponent<ActionScheduler>().StartAction(this);
target = combatTarget.GetComponent<Health>();
}
public void Cancel()
{
StopAttack();
target = null;
GetComponent<Mover>().Cancel();
}
private void StopAttack()
{
GetComponent<Animator>().ResetTrigger("attack");
GetComponent<Animator>().SetTrigger("stopAttack");
}
}
}
using RPG.Core;
using UnityEngine;
namespace RPG.Combat
{
[CreateAssetMenu(fileName = "Weapon", menuName = "Weapons/Make New Weapon", order = 0)]
public class Weapon : ScriptableObject
{
[SerializeField] AnimatorOverrideController animatorOverride = null;
[SerializeField] GameObject equippedPrefab = null;
[SerializeField] float weaponDamage = 5f;
[SerializeField] float weaponRange = 2f;
[SerializeField] bool isRightHanded = true;
[SerializeField] Projectile projectile = null;
public void Spawn(Transform rightHand, Transform leftHand, Animator animator)
{
if (equippedPrefab != null)
{
Transform handTransform = GetTransform(rightHand, leftHand);
Instantiate(equippedPrefab, handTransform);
}
if (animatorOverride != null)
{
animator.runtimeAnimatorController = animatorOverride;
}
}
private Transform GetTransform(Transform rightHand, Transform leftHand)
{
Transform handTransform;
if (isRightHanded) handTransform = rightHand;
else handTransform = leftHand;
return handTransform;
}
public bool HasProjectile()
{
return projectile != null;
}
public void LaunchProjectile(Transform rightHand, Transform leftHand, Health target)
{
Projectile projectileInstance = Instantiate(projectile, GetTransform(rightHand, leftHand).position, Quaternion.identity);
projectileInstance.SetTarget(target);
}
public float GetDamage()
{
return weaponDamage;
}
public float GetRange()
{
return weaponRange;
}
}
}
using System.Collections;
using System.Collections.Generic;
using RPG.Core;
using UnityEngine;
public class Projectile : MonoBehaviour
{
[SerializeField] float speed = 1;
Health target = null;
void Update()
{
if (target == null) return;
transform.LookAt(GetAimLocation());
transform.Translate(Vector3.forward * speed * Time.deltaTime);
}
public void SetTarget(Health target)
{
this.target = target;
}
private Vector3 GetAimLocation()
{
CapsuleCollider targetCapsule = target.GetComponent<CapsuleCollider>();
if (targetCapsule == null)
{
return target.transform.position;
}
return target.transform.position + Vector3.up * targetCapsule.height / 2;
}
}
3, AxeのProjectileにArrowProjectileをアタッチする
ダメージの実装
1, 各スクリプトに下記のコードを書く
using System.Collections;
using System.Collections.Generic;
using RPG.Core;
using UnityEngine;
public class Projectile : MonoBehaviour
{
[SerializeField] float speed = 1;
Health target = null;
float damage = 0; //追加
void Update()
{
if (target == null) return;
transform.LookAt(GetAimLocation());
transform.Translate(Vector3.forward * speed * Time.deltaTime);
}
public void SetTarget(Health target, float damage) //danageを追加
{
this.target = target;
this.damage = damage; //追加
}
private Vector3 GetAimLocation()
{
CapsuleCollider targetCapsule = target.GetComponent<CapsuleCollider>();
if (targetCapsule == null)
{
return target.transform.position;
}
return target.transform.position + Vector3.up * targetCapsule.height / 2;
}
//追加
private void OnTriggerEnter(Collider other)
{
if (other.GetComponent<Health>() != target) return;
target.TakeDamage(damage);
Destroy(gameObject);
}
}
using RPG.Core;
using UnityEngine;
namespace RPG.Combat
{
[CreateAssetMenu(fileName = "Weapon", menuName = "Weapons/Make New Weapon", order = 0)]
public class Weapon : ScriptableObject
{
[SerializeField] AnimatorOverrideController animatorOverride = null;
[SerializeField] GameObject equippedPrefab = null;
[SerializeField] float weaponDamage = 5f;
[SerializeField] float weaponRange = 2f;
[SerializeField] bool isRightHanded = true;
[SerializeField] Projectile projectile = null;
public void Spawn(Transform rightHand, Transform leftHand, Animator animator)
{
if (equippedPrefab != null)
{
Transform handTransform = GetTransform(rightHand, leftHand);
Instantiate(equippedPrefab, handTransform);
}
if (animatorOverride != null)
{
animator.runtimeAnimatorController = animatorOverride;
}
}
private Transform GetTransform(Transform rightHand, Transform leftHand)
{
Transform handTransform;
if (isRightHanded) handTransform = rightHand;
else handTransform = leftHand;
return handTransform;
}
public bool HasProjectile()
{
return projectile != null;
}
public void LaunchProjectile(Transform rightHand, Transform leftHand, Health target)
{
Projectile projectileInstance = Instantiate(projectile, GetTransform(rightHand, leftHand).position, Quaternion.identity);
projectileInstance.SetTarget(target, weaponDamage); //weaponDamageを追加
}
public float GetDamage()
{
return weaponDamage;
}
public float GetRange()
{
return weaponRange;
}
}
}
2, ArrowProjectileにBoxColliderをつけ、サイズ調整、IsTriggerを付ける
矢にエフェクトを実装
1, ArrowProjecttileにTrailを作成する
4, EnemyをPrefabVariantしてArcherを作成する
6, ArrowProjectileをPrefabVariantしてRedとBlueを作成
8, Axeを複製し、AxeBlueProjectileとAxeRedProjectileを作成