- Home /
How do I access/use the variable inside a script when the script name is unknown but objectname is?
I have placed a box collider as a child object to my AI player. This represents my player's weapon. This weapon's box collider sticks out in front of the AI player, and when it collides with an enemy it knows it can start attacking it.
This is all fine and dandy, except I don't know how to access the damage variable within my "Sword" object's script, also called "Sword". I cannot explicitly state "Sword" with a GetComponenet because I never know what weapon the AI player will be starting the game with.
This is how I'm currently pulling the weapon game object by tag (important):
void Start()
{
weapon = FindWeapon();
Debug.Log(weapon.tag + weapon.name);
}
GameObject FindWeapon()
{
GameObject weapon = null;
foreach (Transform child in transform)
{
if (child.tag == "Weapon")
{
weapon = child.gameObject;
}
else
{
weapon = null;
}
}
return weapon;
}
So what do I do now to actually access the variable named "damage" inside the "Sword" script within the child object "Sword"? I will never know what the actual name of the weapon or script might be, so that's why I find it on start. However, I plan on making the weapon names always match the script within it (Sword/Sword).
so if the name of gameobject and script are always the same you could try something like this
int damage = weapon.GetComponent(weapon.name).damage;
This was my initial plan. When I realized GetComponent wasn't smart enough to do this (ugh) I went down the interface route.
@ExtinctSpecie this will not work. as GetComponent does not take a string as input.
Any idea why? Just an oversight or engine limitation?
Answer by EpiFouloux · Feb 28, 2017 at 08:17 AM
Do an abstract class for all weapons and inherit it with the specific ones. this way a global getComponent(WeaponScript) would work.
Thank you! I found similar questions with the same answer (or interfaces). However, they are too... abstract for my understanding and I could not figure out how to implement them for my use case. Can you please show me an example with what I've provided?
Answer by NecrosDk · Feb 28, 2017 at 06:11 PM
I'm doing the exact same thing in a prototype I'm making at the moment:
I have items, that I can pick up, and a type of item would be a weapon. I can also interact with items, so my items extend from my "Interact" class.
So in effect I can pick up all instances of "Weapon" even though the pickup function is not in the "Weapon" class, but in the "Item" class! Neat huh?
So in your case, you might want to define your sword as Sword : Weapon and in your "Weapon" class, define your damage variable as public int/float damage
public class Item : Interact //
{
public ItemSettings settings;
[System.Serializable]
public class ItemSettings{
public Vector3 pickupRotation;
public Vector3 pickupPosition;
public float maxForceMod;
}
public Rigidbody body;
void Start()
{
body = GetComponent<Rigidbody>();
}
public void Pickup()
{
FindObjectOfType<PlayerInteraction>().PickupItem(this);
}
}
//Next file:
public class Weapon : Item //<---- notice how weapon extends item? That means weapon has all the //variables declared in "item", and Weapon is a type of Item.
{
public float attackFraction = 0;
public bool attacking = false;
public enum animationName {
SwingAttack, SmashAttack
};
public animationName animName;
}
And to go even further, here is a type of weapon that I can smash stuff with:
public class SmashWeapon : Weapon
{
public float smashFraction;
private float smashForce = 50;
private float smashRadius = 0.75f;
// Use this for initialization
void Start()
{
}
// Update is called once per frame
void Update()
{
}
public void SmashAttackImpactForce()
{
HitBelow();
float impactForce = smashForce * smashFraction;
float radius = attackFraction * body.mass / 3;
Collider[] hitColliders = Physics.OverlapSphere(transform.position, radius);
for (int i = 0; i < hitColliders.Length; i++)
{
if (hitColliders[i].GetComponent<Rigidbody>() != null)
{
float forceFraction = (1 - $$anonymous$$athf.Clamp((Vector3.Distance(transform.position, hitColliders[i].transform.position) / radius), .4f, .8f)) * attackFraction;
float totalForce = body.mass * impactForce * forceFraction;
hitColliders[i].GetComponent<Rigidbody>().AddExplosionForce(totalForce, transform.position, radius);
hitColliders[i].GetComponent<Rigidbody>().AddForce(Vector3.up * totalForce/ 2);
}
}
}
}
Thank you for the in depth response! Can you go one further and give me two examples of creating two different weapons that inherit the weapon class? And the specific code I need to access the damage variable from within them on my AI player? I'm still not sure how I actually access the Sword script component without knowing it's name. I apologize if this is obvious, but I'm at work and can't quite comprehend it yet.
And again, thank you for the guidance.
Answer by ExtinctSpecie · Mar 04, 2017 at 09:02 AM
using UnityEngine;
using System.Collections;
// attach this to the player
public class Test : MonoBehaviour
{
GameObject[] allWeapons;
GameObject myWeapon;
// Use this for initialization
void Start ()
{
myWeapon = GetWeapon ();
//we got the weapon
Debug.Log(myWeapon.name);
}
// Update is called once per frame
GameObject GetWeapon()
{
allWeapons = GameObject.FindGameObjectsWithTag ("Weapon");
foreach (GameObject g in allWeapons)
{
Debug.Log (g.name);
}
int MyIndex = Random.Range(0,(allWeapons.Length));
Debug.Log ("SELECTED" + allWeapons[MyIndex].name);
return allWeapons[MyIndex];
}
public void Update()
{
int damage = myWeapon.GetComponent<SimpleWeaponBaseClass> ().damage;
Debug.Log (damage);
}
}
using UnityEngine;
using System.Collections;
//attach this to weapon one
public class WeaponBoo : SimpleWeaponBaseClass
{
// Use this for initialization
void Start ()
{
damage = 10;
}
// Update is called once per frame
void Update ()
{
}
}
using UnityEngine;
using System.Collections;
//attach this to weapon 2
public class WeaponWoo : SimpleWeaponBaseClass
{
// Use this for initialization
void Start ()
{
damage = 5;
}
// Update is called once per frame
void Update ()
{
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//the base class for weapons
public class SimpleWeaponBaseClass : $$anonymous$$onoBehaviour {
public int range { get;set; }
public int damage { get; set; }
}