how follow the instantiated object to other instantiated object - c#

i want to follow the instantiated ball to my instantiated player. when my ball follow the player from hierarchy it work fine but when i instantiate the player it does not work .
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ExtraBallController : MonoBehaviour
{
public Transform target;
private int distance = 30;
// Use this for initialization
void Start ()
{
}
// Update is called once per frame
void Update ()
{
this.transform.position = new Vector3 (target.transform.position.x, target.transform.position.y, distance);
}
}

As #Hellium said, there are numerous possibilities. One way is to set the balls' target when the player is instantiated.
Here's a sample code (Not Tested):
GameObject player = Instantiate(playerPrefab, vectorPos, Quaternion.Identity);
ExtraBallController[] balls = FindObjectsOfType(typeof(ExtraBallController)) as ExtraBallController[];
foreach(ExtraBallController ball in balls){
ball.target = player.transform;
}
Hope this helps!

Related

how to make an enemy move towards the player within a certain range using navmesh

I have been attempting to add a "range" of sorts to my enemy movement (too many move toward the player at once) and I have seen one solution but I am uncertain how to implement it as it doesn't really detect that I'm using the dis and distval values.
I am not trying to add any movement or route for them to follow. Just a wide (but not too wide) activation sphere of sorts. (also note that I am new, and I know it's probably a stupid question to ask, but I still don't know the answer to it and can't find it ((or at the very least understand it))).
here is my code.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class Follow : MonoBehaviour
{
public NavMeshAgent enemy;
public Transform Player;
// Update is called once per frame
void Update()
{
var distVal = 5.0f;
var dis = Vector3.Distance(enemy.position, Player.position);
if (dis <= disVal)
{
enemy.SetDestination(Player.position);
}
}
}
If you set a NavMeshAgent's destination to be its own position it will stop moving.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class Follow : MonoBehaviour
{
public NavMeshAgent enemy;
public Transform Player;
// Update is called once per frame
void Update()
{
float distVal = 5.0f;
float dist = Vector3.Distance(enemy.transform.position, Player.position);
if (dist <= distVal)
{
enemy.SetDestination(Player.position);
}
else
{
enemy.SetDestination(enemy.transform.position);
}
}
}
This should do what you want. But I should point out you were never using your distVal variable, and that enemy.position should have been enemy.transform.position.

I can't assign script from another object. Is there smth wrong?

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MeteorRangeController : MonoBehaviour
{
[SerializeField] PlayerController PlayerController; // It has to be script
[SerializeField] GameObject Player; // no problem with assigning this
[SerializeField] Transform playerTransform;
[SerializeField] Vector3 playerPos;
[SerializeField] bool canGo;
[SerializeField] GameObject meteor;
// Start is called before the first frame update
void Start()
{
playerTransform = Player.GetComponent<Transform>();
PlayerController= Player.GetComponent<PlayerController>(); //*The Problem Is Here*
//PlayerController Cannot Be Assigned
}
// Update is called once per frame
void Update()
{
print(PlayerController.IdleTime); //to test it I printed
playerPos = Player.transform.position;
//I tried to take idle time from Player controller here.
if (PlayerController.IdleTime > 2)
{
canGo = true;
}
else
{
canGo = false;
}
if (canGo == true)
{
transform.position = new Vector3(playerPos.x, playerPos.y, playerPos.z);
gameObject.SetActive(true);
Invoke("SetActiveFalse",2f);
}
}
void SetActiveFalse()
{
gameObject.SetActive(false);
meteor.SetActive(true);
Invoke("MeteorSetActiveFalse", 2f);
}
void MeteorSetActiveFalse()
{
meteor.SetActive(false);
}
}
I can't assign it.
I researched it but I couldn't find anything different.
I know it's a very easy question, also I assigned game object player, in it there is a script named PlayerController, and there is a variable named idle time please help me
Okay, that's my first try to answer on topic on Stack Overflow, so hope you will be patient to my mistakes.
Can you say, are you sure, that Player object has a PlayerController script on him?
I think you must use
var isControlSetted = Player.TryGetComponent<PlayerController>(out PlayerController);
instead of:
PlayerController= Player.GetComponent<PlayerController>();
Why? So, that can answer on question №1 and after it you can control the logic of working with it when (use AddComponent for example or throw an exception)
3. Okay, even that can't fix your problem if PlayerController setted on inheritor or ancestor of Player gameobject in gameobject hierarchy
I hope I helped you
Edited:
Okay, I was asked to make answer some clearly, so...
First of all, can you show PlayerController script, pls?
Secondary, why I'm asking to use TryGetComponent instead of GetComponent bcs as I commented below getting null value is not a good practice, but if you want - use it.
Let's look on script more closly
I refactored this pls look
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MeteorRangeController
: MonoBehaviour
{
[SerializeField] PlayerController playerController;
[SerializeField] GameObject playerObject;
[SerializeField] Transform playerTransform;
// [SerializeField] Vector3 playerPos; we don't need this
// [SerializeField] bool canGo; and this
[SerializeField] GameObject meteorObject;
/// <summary>
/// Method that called once we use this or Awake for init our fields/props
/// </summary>
void Start()
{
playerTransform = playerObject.GetComponent<Transform>(); // there no need to use TryGetComponent bcs Transform is req. for every GO/MB
playerController= playerObject.GetComponent<PlayerController>(); // there you could use TryGC, but if you use RequireComponentAttribute that's ok
}
/// <summary>
/// Method that's calls every frame
/// </summary>
void Update()
{
if (playerController.IdleTime <= 2)
return;
transform.position = playerTransform.position;// i really can't understand what hepenning after this so i stop
gameObject.SetActive(true);
Invoke(nameof(SetActiveFalse),2f);
}
void SetActiveFalse()
{
gameObject.SetActive(false);
meteorObject.SetActive(true);
Invoke(nameof(MeteorSetActiveFalse), 2f);
}
void MeteorSetActiveFalse()
{
meteorObject.SetActive(false);
}
}
So, afterwards GO.GetComponent can return null only if the requested GO did not have a Monobehaviour script.
You can check similar question there https://forum.unity.com/threads/getcomponent-doesnt-works.516839/

How i can instantiate a new canvas intos a canvas, and set de screen space on the MainCamera?

i have a canvas with a few GameObjects and i wanna instantiate a new GameObject that contains a canvas, so the porblem is its appears outside of main camera, and i need to set the render camera on the MainCamera of my game.
I have this and it does not work.
Main Camera where the game is running:
img of unity
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class newCanvas: MonoBehaviour
{
// Start is called before the first frame update
public GameObject text; //here i put the text, that I want to appear
private GameObject textD; //i use the for to delete the text
public void Start(){
textoD = Instantiate(text, transform.position, transform.rotation);//instantiate the text, and its instantiated outside of the maincamera of the game
Invoke("DeleteText",2f);//invoke to delete the game object
}
void DeleteText(){
Debug.Log("Delete text");
Destroy(textD);
}
}
i have something like this:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class mainGAme : MonoBehaviour
{
public newCanvas text=null;
void Start(){
text = GameObject.FindObjectOfType<newCanvas>();
Instantiate(newCanvas);
}
void Update(){
}
}
And when i execute thegame, the object is instantiated, it is instantiated outside the maincamera as it doesn't have the render camera set to the game's maincamera.
Some know how to solvet, thank you<3
You need to set the parent of your gameobject's transform to your camera's transform.
https://docs.unity3d.com/ScriptReference/Transform.SetParent.html
Instantiate actually has a overload that allows you to set parent aswell
public static Object Instantiate(Object original, Transform parent);
https://docs.unity3d.com/ScriptReference/Object.Instantiate.html
You can get your camera via static properties in Camera
https://docs.unity3d.com/ScriptReference/Camera.html
You should check out the following docs to get a better understanding of how Transform and Gameobject are used.
https://docs.unity3d.com/ScriptReference/GameObject.html
https://docs.unity3d.com/ScriptReference/GameObject-transform.html
https://docs.unity3d.com/ScriptReference/Transform.html

How can I reference a game object on my scene in a prefab component I have just instantiated?

Currently I am learning both Unity and C#. I am working on a small game where I control a spaceship on the screen, while meteors are spawning in a random position outside of the camera's visible space, then start to move towards the ship.
For this I am trying to refer to the ship game object in a component on a meteor prefab, to get it's position and the angle needed to start moving towards the ship.
public class meteorPath : MonoBehaviour
{
public float speed = 10f;
public Rigidbody2D rb;
public GameObject ship;
void Start()
{
int typeOf = Random.Range(2, 11);
Vector3 posOf = new Vector3(Random.Range(-7f, 7f), Random.Range(16f, 8f), 0);
transform.localScale = new Vector3(typeOf, typeOf, 1);
transform.localPosition = posOf;
}
}
How can I make get the player's position to calculate the angle needed every time I instantiate a meteor?
I'm guessing that you're instantiating everything at runtime.
You would either do:
GameObject.Find(YOUR OBJECT NAME)
GameObject.FindGameObjectWithTag(sometag), only if your player has a tag
Make player's class singleton and reference it from other classes with PlayerClassName.InstanceName and reference the position.
If you're not instantiating everything but is a static scene, then just make a prefab of the meteor with the player's reference inside
one way to get references is to create instanced game manager:
and when meteor is created you have it get player position from that instanced GameManager.
in start of meteor:
private Vector3 playerPosition = GameManager.instance.playerPosition.transform.position;
in GameManager:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GameManager : MonoBehaviour
{
public static GameManager instance;
public GameObject playerPosition;
private void Awake()
{
instance = this;
}

How can I respawn an object in Unity?

I am working on a 3d basketball game in unity.
It has a score and a timer. After a certain time my scene loads and starts from the beginning. Every time I throw the ball, I have to spawn it.
It has a spawn button and a shoot button. But I don't want to use the spawn button. So I want to spawn the ball automatically.
How should I do it? I am giving my spawn button code and throw button code bellow.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SpawnButton: MonoBehaviour
{
public GameObject ball;
public GameObject BallPosition;
public void Spawn()
{
ball.transform.position = BallPosition.transform.position;
var ballPosition = ball.transform.position;
ball.GetComponent<Rigidbody>().useGravity = false;
ball.GetComponent<Rigidbody>().velocity = Vector3.zero;
ball.transform.position = ballPosition;
}
}
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ThrowButton: MonoBehaviour
{
static Animator anim;
public GameObject ball;
public float ballThrowingForce = 5f;
internal bool holdingBall;
void Start()
{
anim = GetComponent<Animator>();
ball.GetComponent<Rigidbody>().useGravity = false;
}
public void Throw()
{
anim.SetTrigger("isThrowing");
StartCoroutine(Test());
}
IEnumerator Test()
{
yield return new WaitForSeconds(1.5f);
ball.GetComponent<Rigidbody>().useGravity = true;
//ball.GetComponent<Rigidbody>().AddForce(transform.up * ballThrowingForce);
ball.GetComponent<Rigidbody>().AddForce(0, 380.0f, ballThrowingForce);
}
}
To spawn a ball you should create a prefab and instantiate it. Example:
private class Spawner : MonoBehaviour
{
public GameObject prefab;
public GameObject Spawn() => Instantiate(prefab);
}
So that your throw code should spawn a ball and if you want destroy an older one.
The above answer by Iv Misticos mentioned the use of Instantiate which is a great way to spawn a new ball.
before you spawn a new ball, you need to specify when it must spawn.
Either you can
use a Invoke("SpawnNewBallMethod",3) //after this piece of code is executed, it waits for 3 seconds and executes the method you mention in it which can have the code to instantiate.
Or After the first ball's work is done, you can destroy it(Destroy(ball)) or set active to false - Then check the state (if it exists(null check?) or gameObject.active==true) and accordingly instantiate a new ball (if it is setactive(false) don't forget to destroy it later).
Although gameObject.active is obsolete, it will serve the purpose without complicating things.
In my opinion, Invoke is better than a IEnumerator here as Invoke will not stop the execution flow and continue with the other things while the timer is running.

Categories

Resources