We’re getting very close to a fully functioning combat system with both melee and shooting. In this lecture we launch our projectile.
Great job Rick! Can’t wait to see where we take all this
Just a question about ScriptableObjects vs GameObjects. From what I can understand we could also use a GO prefab to serve the same functionality as the SO, but the reason we don’t is the SO has a lower resources overhead, since everything is serialized and Unity only needs to load that single asset (if I understood correctly).
My question now is what happens if we want to change a field on the SO? For instance if I wanted to set the Projectile to be an ice arrow, fire arrow, or normal arrow dynamically depending upon the type of arrow equipped, even though the bow remains the same, how would I dynamically update the SO to do this? From what I thought I understand SO’s are similar to static objects in that we shouldn’t or can’t change it at run time to do this. Would a GO be better for this or have I completely misunderstood SOs? I’m new to Unity so thanks for the patience.
im having trouble with this system. I have the code all working and done. However my Bow is not allowing me to attach my Arrow onto it
and just to show, i do have the Projectile script on my arrow prefab
im unsure why my Bow dosent even see any of my projectile prefabs
So after some trial and error i got it to work, for some reason it dosent appear in the Select projectile box, and i need to go into the Games folder to drag and drop, i was trying to from the hierarchy
I have been having alot of issues with my Bow, so im just going to put them all into this reply. When im shooting my bow, it also makes my movement kinda glitchy, and it even passively moves me backwards if im shooting my bow while someone attacks me. No idea how to fix this
another issue im having, is the collider isnt workering properly on my arrow
i put those two print statements to help me Debug it and “test1” prints, but “test” does not. SO i fixed this particular issue by adding a rigid body to my projectile
EDIT: Through trial and error and some advice from people, i finally fixed all my issues!
Unfortunately, Unity has a quirk where the selector can only pick up built in components. It simply can’t see custom monobehavior scripts. This makes it necessary to drag the prefabs into the inspector manually.
I’m also having trouble getting my Projectile prefab to link up with my Bow. I’m trying to drag it into the Projectile projectile field in the Investigator panel, but it’s not letting me.
The code for my Projectile and relevant Weapon are pasted below, any ideas why this isn’t working? Thanks a lot.
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using RPG.Core;
namespace RPG.Combat
{
public class Projectile : MonoBehaviour
{
[SerializeField] float speed = 1;
Health target = null;
// Update is called once per frame
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 * 0.6f);
}
}
}
using RPG.Core;
using UnityEngine;
namespace RPG.Combat
{
[CreateAssetMenu(fileName = "Weapon", menuName = "Weapons/Make New Weapon", order =0 )]
public class Weapon : ScriptableObject
{
[SerializeField] GameObject equippedPrefab = null;
[SerializeField] AnimatorOverrideController animatorOverride = null;
[SerializeField] float weaponDamage = 5f;
[SerializeField] float weaponRange = 2f;
[SerializeField] float timeBetweenAttacks = 1f;
[SerializeField] bool isRightHanded = true;
[SerializeField] Projectile projectile;
public void SpawnWeapon(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 == true)
{
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;
}
public float GetTimeBetweenAttacks()
{
return timeBetweenAttacks;
}
}
}
You won’t be able to load it using the Selection circle, due to a quirk in Unity. You’ll have to drag it from the Assets folder directly into the projectile field. Make sure you’re dragging the prefab from the assets folder, not an arrow in the scene itself, as the inspector you’ve pasted seems to show.
Yup, that did the trick, I had to drag it from the Assets folder. Thanks!
I am unable to Instantiate the arrow?
public void LaunchProjectile(Transform rightHand, Transform leftHand, Health target) //, GameObject instigator, float calculatedDamage
{
Debug.Log("Projectile name : " + projectile.name); *** <<----- This shows in Console
Projectile projectileInstance = Instantiate(projectile, GetTransform(rightHand, leftHand).position, Quaternion.identity); *** << --- arrow does not come into scene(does not Instaniate)
projectileInstance.SetTarget(target); //, instigator, calculatedDamage
}
Any ideas?
Creating a Projectile seems easy.
- Put empty gameObject into scene
- Name it Arrow2
- Add Projectile script to it
- add a mesh (an object arrow)
- Drag into prefab folder to be able to drag it into Bow SO
- Delete it from scene.
I have to be missing something? what?
Thanks
{SOLVED] seems actually it does Instaniate but gets destroy to quick so I added time in SetTarget as below, and now I can see them fly and hit target.
public void SetTarget(Health target)
{
this.target = target;
Destroy(gameObject, 5f); ***** added 5f to allow time to see in air
}
hmm… curious
Yes, if the time in Destroy is too low (or worse, is left off) then it may appear it never got spawned…
A bit of syntax on that…
The complete signature for Destroy is
public void Destroy(GameObject toDestroy, float time=0.0f);
When you just say Destroy(gameObject), then it assumes a time of 0.0f; which basically means now