C# and Unity getting errors that confuse me - c#

I am brand new at this, and I am having a few conundrums about this code that I put in. I followed a tutorial and I am still having some issues. All I want to do is move the object that I have this script attached to called Player, and the script is PlayerMovement.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour {
public object Player(PlayerMovement) { // Identifier expected, and 'PlayerMovement.Player(PlayerMovement)' not all codes return a value
{
if (Input.GetKeyDown(KeyCode.W))
{
Transform.Translate(Vector3.forward * Time.deltaTime); //ERROR: An object reference is required for the non-static field, method or property 'Transform.Translate(vector3)
Debug.Log("W is pressed, and I should move forwards.");
}
if (Input.GetKeyDown(KeyCode.S))
{
Debug.Log("S is pressed, and I should move backwards.");
}
if (Input.GetKeyDown(KeyCode.A))
{
Debug.Log("A is pressed, and I should move left.");
}
if (Input.GetKeyDown(KeyCode.D))
{
Debug.Log("D is pressed, and I should move right.");
}
}
}
On line 22 I am getting 2 errors Identefier expected, and 'PlayerMovement.Player(PlayerMovement)' not all codes return a value.
On line 29 I am getting An object reference is required for the non-static field, method or property 'Transform.Translate(vector3)'
As I am brand new, I have been looking up answers for hours upon hours and every answer I come across whenever I google anything doesn't actually explain what I am doing wrong, or I just am not reading it properly.

The error on line 22 is caused by the function Player being of type object and you don't return an object in the method. If you replace:
public object Player(PlayerMovement)
with:
public void Player(PlayerMovement)
That error should go away or you could return an object but I am not sure what that would be.

First of all, as Spirit carp said. the program will expecting a return value so you should either return a value or change object to void
public object Player....
into a
public void Player....
and then the main problem is you are invoking the Transform.Translate instead of changing the actual transform of your gameObject.
as you said the PlayerMovement script is attached on your player gameobject so the goal is to make the gameobject change it's transform depends on the key input. try to invoke the transform itself not the class Transform. transform is the actual transform of the gameobject and Transform is the class so you are invoking an static method, instead try to use this.transform.Translate
this.transform.Translate(Vector3.forward * Time.deltaTime);
then the last thing make sure to call your method inside Update method to make it works

Related

I cant assign my GameObject variable. Please assist

I am trying to assign ScriptManager to ObjectManager, and used the line :
ObjectManager = GameObject.Find("ScriptManager");
I have checked multiple times to make sure "ScriptManager" is spelt correct, Ive even tried copy pasting the name straight from Unity.
I recieve this error when running:
"UnassignedReferenceException: The variable ObjectManager of Mining has not been assigned.
You probably need to assign the ObjectManager variable of the Mining script in the inspector.
UnityEngine.GameObject.GetComponent[T] () (at <3be1a7ff939c43f181c0a10b5a0189ac>:0)
Mining.Sell () (at Assets/Mining.cs:49)"
I sadly cant assign the variable straight from the inspector, because the object with the code attached is loaded using a Prefab.
here is the full code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Mining : MonoBehaviour
{
public GameObject ObjectManager;
public Text WorkerCountText;
public float MiningSpeed;
public float WorkersInMine;
public float MiningMultiplyer;
public Collider2D collider;
public GameObject DropDown;
private float WorkerCount;
private float MineWorth;
private float Cash;
// Start is called before the first frame update
void Start()
{
ObjectManager = GameObject.Find("ScriptManager");
collider = GetComponent<Collider2D>();
DropDown.SetActive(false);
}
// Update is called once per frame
void Update()
{
Cash = ObjectManager.GetComponent<GenerateItems>().Money;
WorkerCount = ObjectManager.GetComponent<GenerateItems>().Workers;
MineWorth = ObjectManager.GetComponent<GenerateItems>().MineCost;
WorkerCountText.text = "Workers:" + WorkerCount;
}
public void Sell()
{
ObjectManager.GetComponent<GenerateItems>().Money = Cash + MineWorth;
Object.Destroy (this);
}
}
I would change the way how you assign the ScriptManager to ObjectManager. The function Find() is not very reliable and in case if anything changes in hierarchy or in the name of the GameObject, the function will not find the desired GameObject.
There are multiple ways how you can assign the GameObject to the ObjectManager, including more reliable function FindObjectOfType(), or simply creating variable:
public GameObject objectManager;
and dragging your ObjectManager from the hierarchy into the inspector in the ScriptManager GameObject.
Note: If you want to use any function of the ObjectManager you would need to get that component in the Start function of the ScriptManager.
Try using Object.FindObjectOfType
https://docs.unity3d.com/ScriptReference/Object.FindObjectOfType.html
I have discovered how to fix it!
For anyone wondering, the object this is attacked to is a prefab. And is only loaded once the player purchases the item. Meaning it is not loaded when Start() is executed. Moving the line into Sell() , Add() , and remove assigns it when the buttons are clicked. This fixed the error. Thank you to everyone who tried to help, I am now also using FindGameOBjectWithTag instead of Find to make sure it always works

'Component.GetComponent<T>()' is a method, which is not valid in the given context [Assembly-CSharp]csharp(CS0119)

When I try to get a variable from another script I get the error 'Component.GetComponent<T>()' is a method, which is not valid in the given context [Assembly-CSharp]csharp(CS0119)
The code that's throwing the error is here
GetComponent<EnemyAI>.Attack();
Any help or suggestions is greatly appreciated,
In fact, you can't get the component class just by writing the type in any code, and to do this you need to have an instance of the enemyAI gameObject as a reference. In this solution The easiest way to do this is to use GameObject.FindObjectOfType<>() like the code below:
public EnemyAI enemyAI; // define a variable for enemyAI
public void Start()
{
enemyAI = FindObjectOfType<EnemyAI>(); // it will find your enemyAI script gameObject
}
Once the game is begining, EnemyAI is stored in that variable, and you have access to the class properties. And you can easily run the methods.
private void OnNearEnemy()
{
enemyAI.Attack(); // call attack function
enemyAI.power += 10f; // add some power for example...
}
Now if you have another component like Rigidbody or Animator in EnemyAI, you can easily call and access it with GetComponent<>().
public void ForceEnemyToEscape()
{
var enemyAgent = enemyAI.GetComponent<NavMeshAgent>(); // get nav mesh
enemyAgent.destination = transform.position + transform.forward * 10f;
}
However, I suggest you learn object-oriented programming topics well. Because many calls can be made inside the enemy class. I hope it helped.

Unity how to check what object triggered a trigger

I am in the middle of creating a simple 3d platformer in unity and i'm trying to make it so if you are in a certain radius and you hit the "f" key the enemy will disappear. the way i'm checking to make sure the enemy is close enough to be attacked is to have trigger sphere and when its triggered and you press "f" the enemy will be removed. i'm currently trying to see what collided with the trigger but i cant figure it out. here is my current code
using UnityEngine;
public class PlayerCombat : MonoBehaviour
{
public GameObject Enemy1;
public GameObject Enemy2;
public GameObject Enemy3;
public GameObject Enemy4;
// Update is called once per frame
void OnTriggerEnter (Trigger triggerInfo)
{
if (triggerInfo.collider.tag == "Enemy" & Input.GetKey("f"))
{
if (triggerInfo.collider.name == Enemy)
{
Enemy1.SetActive(false);
}
}
}
}
The signature is and has always been OnTriggerEnter(Collider) otherwise that message method will not be recognized by Unity and not get called at all!
And then you already have the according Collider ... what else do you need?
public class PlayerCombat : MonoBehaviour
{
// There is no need to know the enemy references beforehand at all
// you will get all required references from the Collider parameter of OnTriggerEnter itself
// I personally would however expose these two settings to the Inspector to be more flexible
// this way you can adjust these two settings within Unity without having to touch your code
public string listenToTag = "Enemy";
public KeyCode listenToKey = KeyCode.F;
// The signature has to be this otherwise the message method is never invoked at all
private void OnTriggerEnter (Collider other)
{
// Rather use "CompareTag" instead of `==` since the latter will silently fail
// for typos and nonexistent tags while "CompareTag" shows an error which is good for your debugging
// And in general you want to use the logical "&&" instead of the bitwise operator "&" for bools
if (other.CompareTag(listenToTag) && Input.GetKey(listenToKey))
{
// simply set the object you collide with inactive
other.gameObject.SetActive(false);
}
}
}
Finally just make sure that all your enemy instances actually have the tag Enemy
First, I'm pretty sure OnTriggerEnter takes a Collider as its parameter, no? https://docs.unity3d.com/ScriptReference/Collider.OnTriggerEnter.html
You can get the name of the collided object like so
//Upon collision with another GameObject,
private void OnTriggerEnter(Collider other)
{
Debug.Log($"collided with {other.gameObject.name}");
//you can check for specific components too
MyComponent myComponent = other.GetComponent<MyComponent>();
if (myComponent != null) {
// do something if it has that component on it!
}
}

How to get access to the target that has been instantiated in Unity?

I am making a game where I need to spawn a player in the start of the game. Then I will get transform.position of that player but I dont know how to do that. Here is my code:
GameObject playerball;
Transform spawpoint;
bool spaw
private void Start(){
spaw = false;
}
private void Update()
{
if(!spaw)
{
Instantiate(playerball, spawpoint.position, spawpoint.rotation);
spaw=true;
}
//????????????
}
As you see, I have no idea how to get access to that playerball. That playerball is the prefab that holds the control script, and this script has 'Transform public Camera' but in the prefab 'public Transform Camera ' is 'None(Transform)'. So I need that, when I have instantiated the playerball, I can control it, that mean I can set which is 'public Transform camera'. How can I do that?
Instantiate returns a reference to the object you have just instantiated. You just have to keep that reference, and to work on it for your own needs:
GameObject instance = Instantiate(playerball, spawpoint.position, spawpoint.rotation);
Also, you are missing a semicolon on this line:
bool spaw
Whole code would then give:
GameObject playerball;
Transform spawpoint;
bool spaw;
GameObject playerballObject;
private void Start(){
spaw = false;
}
private void Update()
{
if(!spaw)
{
playerballObject = GameObject.Instantiate(playerball, spawpoint.position, spawpoint.rotation);
spaw=true;
// Do any first time modification you need on your object.
}
// Use your reference there to update the state of your object.
}
Alternative script, making a few changes that Isuka did not, for efficiency, clean-code, and good practice.
public GameObject playerballPrefab;
public Transform spawpoint;
private GameObject playerballInstance;
private void Update()
{
if(playerballInstance == null)
{
playerballInstance = Instantiate(playerballPrefab, spawpoint.position, spawpoint.rotation);
// Other spawn logic / modification
}
//do stuff with playerballInstance every frame
}
Notice that we no longer need the bool spawn variable (er, spaw which is misspelled) as we can check to see if the playerballInstance is null, and if it is, spawn it. Any time it is null (e.g. if it is destroyed by any means) we will spawn a new one (which I renamed to playerballPrefab just so that the variable's name indicates that this object is not in the scene hierarchy; purely optional), just as if spawn was reset to false by an external script, but without any potential conflicts (e.g. setting spawn to false without destroying the instance and vice versa).
Additionally we hold that reference in perpetuity so that the ball can be acted upon continuously, rather than for the single frame it was instantiated. Isuka edited their answer to include this change.
playerballInstance can be set as either public (because we wish an outside script to modify the value) or private (because no other script should be touching it). The prefab and transform are declared public because presumably they are defined in the editor / inspector (and private fields are not listed and not serializable).
Start method is no longer needed because we no longer have a spawn value to make sure is set as we want (as well as not needed originally, as the default value for a bool is false and the fact that we could declare bool spawn = false without the Start() method anyway).
Marking Start() and Update() as private is also not strictly necessary, but not wrong. Similarly marking it public is not necessary or wrong. I personally either leave it off (inheriting its protection level from MonoBehaviour) or mark it public (as all MonoBehaviours have this method declared). It makes no difference to the engine what protection level is used, as it is invoked through voodoo.

Unity get a reference of an Object created in a different script

My player object has 4 children objects, called Pawn 1 through 4. When I click on one of them, it becomes selected. When a Pawn is selected, it should glow. Now, the trouble is that in order for glowing to happen properly, each Pawn has to know if it is selected at the moment, or not. I did that part by attaching a
public class PlayerController : MonoBehaviour {
public GameObject selectedObject;
}
to the Player object, and a script to each Pawn object that, among other things, does this
void Update()
{
if (transform.parent.gameObject.GetComponent<PlayerController>().selectedObject ==
gameObject)
{
Glow();
}
}
I can't help but to think that there has to be a better way to do this, as performing a GetComponent on every Update, on every Pawn, for every player seems incredibly wasteful.
Is there a way to get a reference to the selectedObject in Start(), so it keeps getting updated without manually getting it the whole time?
Is there a way to get a reference to the selectedObject in Start(), so
it keeps getting updated without manually getting it the whole time?
Cache PlayerController in the Start function.
private PlayerController playerController;
void Start()
{
playerController = transform.parent.gameObject.GetComponent<PlayerController>();
}
void Update()
{
if (playerController.selectedObject ==
gameObject)
{
Glow();
}
}
Why not have the Pawn handle the click interaction and store whether or not it is selected? Then you'd have something like:
if(IsSelected)
Glow();

Categories