I don’t know what happen, after i implemented this part of the integration process, my player doesn’t use the range weapons as range weapons, it’s always trying to get in close range. Meanwhile the enemies can use arrows and fireballs without problem, so it’s not a problem of the raycasting or something else.
Here is my code in the fighter and weapon config. The code has some difference to the lesson because i progressed until the lesson 62 of this course. Which means i have implemented StatsEquipment and RandomDropper.
This is Fighter:
using UnityEngine;
using RPG.Movement;
using RPG.Core;
using GameDevTV.Saving;
using RPG.Attributes;
using RPG.Stats;
using GameDevTV.Utils;
using GameDevTV.Inventories;
namespace RPG.Combat{
public class Fighter : MonoBehaviour, IAction, ISaveable{
[SerializeField] float timeBetweenAttacks = 1f;
[SerializeField] Transform rightHandTransform = null;
[SerializeField] Transform leftHandTransform = null;
[SerializeField] WeaponConfig defaultWeapon = null;
Health target;
Equipment equipment;
float timeSinceLastAttack = Mathf.Infinity;
WeaponConfig currentWeaponConfig;
LazyValue<Weapon> currentWeapon;
private void Awake(){
currentWeaponConfig = defaultWeapon;
currentWeapon = new LazyValue<Weapon>(SetupDefaultWeapon);
equipment = GetComponent<Equipment>();
if(equipment) equipment.equipmentUpdated += UpdateWeapon;
}
private void Start(){
//if(currentWeapon == null) EquipWeapon(defaultWeapon);
currentWeapon.ForceInit();
}
private void Update(){
timeSinceLastAttack += Time.deltaTime;
if(target == null) return;
if(target.GetIsDead()) return;
if (!GetIsInRange(target.transform)){
GetComponent<Mover>().MoveTo(target.transform.position, 1f);
} else{
GetComponent<Mover>().Cancel();
AttackBehaviour();
}
}
//Private
private Weapon SetupDefaultWeapon(){
return AttachWeapon(defaultWeapon);
}
private Weapon AttachWeapon(WeaponConfig weapon){
Animator animator = GetComponent<Animator>();
return weapon.Spawn(rightHandTransform, leftHandTransform, animator);
}
private bool GetIsInRange(Transform targetTransform){
return Vector3.Distance(transform.position, targetTransform.position) < currentWeaponConfig.WeaponRange();
}
private void AttackBehaviour(){
transform.LookAt(target.transform);
if(timeSinceLastAttack > timeBetweenAttacks){
//This will trigger the Hit() event.
TriggerAttack();
timeSinceLastAttack = 0;
}
}
private void UpdateWeapon(){
var weapon = equipment.GetItemInSlot(EquipLocation.Weapon) as WeaponConfig;
if(weapon == null) AttachWeapon(defaultWeapon);
else AttachWeapon(weapon);
}
//Animations
private void TriggerAttack(){
GetComponent<Animator>().ResetTrigger("Stop Attack");
GetComponent<Animator>().SetTrigger("Attack");
}
private void TriggerStopAttack(){
GetComponent<Animator>().ResetTrigger("Attack");
GetComponent<Animator>().SetTrigger("Stop Attack");
}
//Animation Event
void Hit(){
if(target == null) return;
float damage = GetComponent<BaseStats>().GetStat(Stat.Damage);
if (currentWeapon.value != null) currentWeapon.value.OnHit();
if (currentWeaponConfig.HasProjectile()){
currentWeaponConfig.LaunchProjectile(rightHandTransform, leftHandTransform, target, gameObject, damage);
}
else target.TakeDamage(gameObject, damage);
}
void Shoot(){
Hit();
}
//Public
public void EquipWeapon(WeaponConfig weapon){
currentWeaponConfig = weapon;
currentWeapon.value = AttachWeapon(weapon);
}
public bool CanAttack(GameObject combatTarget){
if (combatTarget == null) return false;
if (!GetComponent<Mover>().CanMoveTo(combatTarget.transform.position) &&
!GetIsInRange(combatTarget.transform)) return false;
Health targetToTest = combatTarget.GetComponent<Health>();
return targetToTest != null && !targetToTest.GetIsDead();
}
public void Attack(GameObject combatTarget){
GetComponent<ActionScheduler>().StartAction(this);
target = combatTarget.GetComponent<Health>();
}
public void Cancel(){
TriggerStopAttack();
target = null;
GetComponent<Mover>().Cancel();
}
public Health GetTarget(){
return target;
}
public object CaptureState(){
return currentWeaponConfig.name;
}
public void RestoreState(object state){
if(state is string weaponName){
WeaponConfig weapon = Resources.Load<WeaponConfig>(weaponName);
EquipWeapon(weapon);
}
}
}
}
This is WeaponConfig:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Unity.VisualScripting;
using RPG.Attributes;
using GameDevTV.Inventories;
using RPG.Stats;
namespace RPG.Combat{
[CreateAssetMenu(fileName = "Weapon", menuName = "Weapons/Make New Weapon", order = 0)]
public class WeaponConfig : EquipableItem, IModifierProvider{
[SerializeField] Weapon equippedPrefab = null;
[SerializeField] AnimatorOverrideController animatorOverride = null;
[SerializeField] Projectile projectile = null;
[SerializeField] float weaponRange = 5f;
[SerializeField] float weaponDamage = 5f;
[SerializeField] float percentageBonus = 0f;
[SerializeField] bool isRightHanded = true;
const string weaponName = "Weapon";
//Public
public Weapon Spawn(Transform rightHand, Transform leftHand, Animator animator){
DestroyOldWeapon(rightHand, leftHand);
Transform handTransform = GetTransform(rightHand, leftHand);
Weapon weapon = null;
if (equippedPrefab != null) {
weapon = Instantiate(equippedPrefab, handTransform);
weapon.gameObject.name = weaponName;
}
var overrideController = animator.runtimeAnimatorController as AnimatorOverrideController;
if (animatorOverride != null) animator.runtimeAnimatorController = animatorOverride;
else if (overrideController != null) animator.runtimeAnimatorController = overrideController.runtimeAnimatorController;
return weapon;
}
public float WeaponRange(){
return weaponRange;
}
public float WeaponDamage(){
return weaponDamage;
}
public float PercentageBonus(){
return percentageBonus;
}
public bool HasProjectile(){
return projectile != null;
}
public void LaunchProjectile(Transform rightHand, Transform leftHand, Health target, GameObject instagator, float calculatedDamage){
Projectile projectileInstance = Instantiate(projectile, GetTransform(rightHand, leftHand).position, Quaternion.identity);
projectileInstance.SetTarget(target, instagator, calculatedDamage);
}
public IEnumerable<float> GetAdditiveModifiers(Stat stat){
if(stat == Stat.Damage) yield return weaponDamage;
}
public IEnumerable<float> GetPercentageModifiers(Stat stat){
if(stat == Stat.Damage) yield return percentageBonus;
}
//Private
private Transform GetTransform(Transform rightHand, Transform leftHand){
if(isRightHanded) return rightHand;
else return leftHand;
}
private void DestroyOldWeapon(Transform rightHand, Transform leftHand){
Transform oldWeapon = rightHand.Find(weaponName);
if(oldWeapon == null) oldWeapon = leftHand.Find(weaponName);
if(oldWeapon == null) return;
oldWeapon.name = "DESTROYING";
Destroy(oldWeapon.gameObject);
}
}
}
Thank you very much in advance to anyone who gives it a look.