Scripts won't affect clones - c#

I made a script which swaps two game objects on click.But the script won't work because the objects are actualy clones of the original prefab.
This is the script(java) :
#pragma strict
var object1 : GameObject;
var object2 : GameObject;
function OnMouseDown ()
{
Instantiate(object2,object1.transform.position,object1.transform.rotation);
Destroy(object1);
}
I use this script to create other game objects (clones)[c#] :
using UnityEngine;
using System.Collections;
public class Spawner : MonoBehaviour {
public GameObject[] obj;
public float spawnMin = 1f;
public float spawnMax = 2f;
// Use this for initialization
void Start () {
Spawn ();
}
void Spawn()
{
Instantiate(obj[Random.Range(0, obj.GetLength(0))],transform.position, Quaternion.identity);
Invoke ("Spawn", Random.Range (spawnMin, spawnMax));
}
}
The objects get renamed to NAME (Clone).
What I wanna do is make the script affect clones too.So they will swap when I click on them.

Related

Is there any way to assign player to Camera after the game started in unity?

Okay, so I create an endless runner game that has character selection. The goal is, when the scene starts (with no player in the hierarchy), the game manager will instantiate the player based on the selected player. But, the CameraController, have the error "Object reference not set to an instance of an object", it cannot find the instantiate player object
Here is how I instantiate my player:
void Start()
{
int selectedCharacter = PlayerPrefs.GetInt("selectedChar");
GameObject prefab = characterPrefabs[selectedCharacter];
GameObject clone = Instantiate(prefab, playerStartPoint, Quaternion.identity);
player = FindObjectOfType<PlayerScript>();
platformStartPoint = platformGenerator.position;
scoreManager = FindObjectOfType<ScoreManager>();
Reset();
}
And this is my camera script:
public class CameraController : MonoBehaviour{
public PlayerScript player;
private Vector3 lastPlayerPosition;
private float distToMove;
// Start is called before the first frame update
void Start()
{
player = FindObjectOfType<PlayerScript>();
lastPlayerPosition = player.transform.position;
}
// Update is called once per frame
void Update()
{
distToMove = player.transform.position.x - lastPlayerPosition.x;
transform.position = new Vector3(transform.position.x + distToMove, transform.position.y, transform.position.z);
lastPlayerPosition = player.transform.position;
}
}
The camera should be move along with the character, do you have any idea how to fix this? Thank you
I'm assuming your Camera tries to search for the player before they get instantiated based on what you mentioned. There are several different approaches to fixing this.
Method 1
Have the script that instantiates the player grab the camera and assign the player instance.
Example
// Call this after instantiating a player instance
FindObjectOfType<CameraController>().AssignTarget(player);
// Add this to CameraController.cs
public void AssignTarget(PlayerScript player)
{
this.player = player;
lastPlayerPosition = player.transform.position;
}
Method 2
Add an event field somewhere that informs when player has been instantiated and subscribe to it using your camera.
Example
using System;
using UnityEngine;
public class PlayerScript : MonoBehaviour
{
public static event Action<PlayerScript> InstanceStarted;
private void Start()
{
InstanceStarted?.Invoke(this);
}
}
using UnityEngine;
public class CameraController : MonoBehaviour
{
private Player player;
private void Start()
{
player = FindObjectOfType<PlayerScript>();
if (player == null)
PlayerScript.InstanceStarted += OnPlayerInstanceStarted;
}
private void OnPlayerInstanceStarted(PlayerScript instance)
{
PlayerScript.InstanceStarted -= OnPlayerInstanceStarted;
player = instance;
}
}
Method 3
Add DefaultExecutionOrder attribute to your scripts and change the execution order to ensure that the player gets instantiated before the Camera starts to look for one.
Example
[DefaultExecutionOrder(100)]
public class TestScript : MonoBehaviour {}
Method 4
Have a Coroutine that periodically checks whether an instance of a player is available before allowing the Camera to do anything.
Example
using System.Collections;
using UnityEngine;
public class CameraController : MonoBehaviour
{
private PlayerScript player;
private void Start()
{
StartCoroutine(StartOncePlayerIsFound());
}
private IEnumerator StartOncePlayerIsFound()
{
player = FindObjectOfType<PlayerScript>();
while (player == null)
{
// Feel free to yield "WaitForEndOfFrame" or "null"
// if you wish to search for player every frame
yield return new WaitForSeconds(0.1f);
player = FindObjectOfType<PlayerScript>();
}
// ...
}
}
Try this one
transform.position = new Vector3(player.transform.position.x, transform.position.y, transform.position.z);

Spawner With error message :member names cannot be the same as their enclosing type

I am making a infinite runner and in the spawn script it always this error message and cant figure out how to fix it : Assets/Scripts/Spawn.cs(16,14): error CS0542: `Spawn.Spawn()': member names cannot be the same as their enclosing type.
using UnityEngine;
using System.Collections;
public class Spawn : MonoBehaviour
{
public GameObject[] obj;
public float spawnMin = 1f;
public float spawnMax = 2f;
// Use this for initialization
void Start()
{
// Spawn();
}
void Spawn()
{
Instantiate(obj[Random.Range(0, obj.GetLength(0))], transform.position, Quaternion.identity);
Invoke("Spawn", Random.Range(spawnMin, spawnMax));
}
}
The name of your class is the-same as a another function(Spawn) inside the class. Simply rename your Spawn() function to something else and your problem should be solved. Maybe, make the S in your spawn function name to be lowercase while the one in your script name capitalized?
void spawn () {
...
}

How can i change each gameobject movement speed?

In the Hierarchy i have 2 ThirdPersonController.
In the Window > Animator i created new empty state called it Walk and set it to HumanoidWalk so when running the game both players are walking.
On one of them i added the script and as Prefab the second ThirdPersonController(1).
Then when running the game it's making clones of the ThirdPersonController(1).
So i see in the Hierarchy more N ThirdPersoncontrollers.
Today to change the speed of walking for each ThirdPersonController i change in the Inspector the Move Speed Multiplier.
But if i want in the script already when creating the clones to set to each one another speed how can i do it ?
using UnityEngine;
using System.Collections;
public class Multiple_objects : MonoBehaviour {
public GameObject prefab;
public GameObject[] gos;
public int NumberOfObjects;
void Awake()
{
gos = new GameObject[NumberOfObjects];
for(int i = 0; i < gos.Length; i++)
{
GameObject clone = (GameObject)Instantiate(prefab, Vector3.zero, Quaternion.identity);
gos [i] = clone;
}
}
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
}
}
What i tried now is to get the Animator component of the Prefab and set the speed to all the clones:
using UnityEngine;
using System.Collections;
public class Multiple_objects : MonoBehaviour {
public GameObject prefab;
public GameObject[] gos;
public int NumberOfObjects;
private Animator _animaotr;
void Awake()
{
gos = new GameObject[NumberOfObjects];
for(int i = 0; i < gos.Length; i++)
{
GameObject clone = (GameObject)Instantiate(prefab, Vector3.zero, Quaternion.identity);
gos [i] = clone;
_animaotr.speed = 10;
}
}
// Use this for initialization
void Start () {
_animaotr = prefab.GetComponent<Animator> ();
}
// Update is called once per frame
void Update () {
}
}
But the main problem is that on my first ThirdPersonController in the Hierarchy the original one i created in Window > Animator empty state called it Walk and set HumandoidWalk.
Now to set the speed for some reason changing the Animator speed never effect of anything for example:
_animaotr.speed = 10;
Only when changing the speed in the ThirdPersonController > Inspector > Third Person Character (Script) > Move Speed Multiplier. And it's changing the same speed to all ThirdPersoncontrollers in the Hierarchy including this i clone.
But how do i change each clone speed to another vlaue of speed ? And why the _animator.speed not changing anything and i need to use this Move Speed Multiplier ?
The Move Speed Multiplier property that is showing in the Editor is declared as m_MoveSpeedMultiplier in the ThirdPersonCharacter script. It is delacre as float m_MoveSpeedMultiplier = 1f; which means that it is a private variable and cannot be accessed from another script. The reason it is showing up in the Editor is because it has [SerializeField] on top of it which means that it is a serialized private variable.
To access it during run-time, you have to change from float m_MoveSpeedMultiplier = 1f; to public float m_MoveSpeedMultiplier = 1f; in the ThirdPersonCharacter script.
Use GetComponent to get instance of ThirdPersonCharacter from the gos GameObject then save it somewhere for re-usual. Since you have 2 ThirdPersonCharacter, you can create two ThirdPersonCharacter arrays to hold those instances. It should look like the code below:
using UnityEngine;
using System.Collections;
using UnityStandardAssets.Characters.ThirdPerson;
public class Multiple_objects : MonoBehaviour
{
public GameObject prefab;
public GameObject[] gos;
public int NumberOfObjects;
private ThirdPersonCharacter[] thirdPersonCharacter;
void Awake()
{
thirdPersonCharacter = new ThirdPersonCharacter[2];
gos = new GameObject[NumberOfObjects];
for (int i = 0; i < gos.Length; i++)
{
GameObject clone = (GameObject)Instantiate(prefab, Vector3.zero, Quaternion.identity);
gos[i] = clone;
thirdPersonCharacter[i] = clone.GetComponent<ThirdPersonCharacter>();
}
}
// Use this for initialization
void Start()
{
thirdPersonCharacter[0].m_MoveSpeedMultiplier = 5f;
thirdPersonCharacter[1].m_MoveSpeedMultiplier = 5f;
}
// Update is called once per frame
void Update()
{
}
}

Accessing start () function from another script error ?

How can i access start() function from another script since start function can be only defined once
This is the script containing start() -
using UnityEngine;
using System.Collections;
public class MoverBolt : MonoBehaviour {
public PlayerControl obj ;
public float speed ;
public Rigidbody rb;
void Start(){
rb = GetComponent<Rigidbody>();
rb.velocity = transform.forward * speed;
}
}
Script which need to access start()
using UnityEngine;
using System.Collections;
[System.Serializable]
public class Boundary{
public float xMax,xMin,zMax,zMin;
}
public class PlayerControl : MonoBehaviour
{
public Boundary boundary ;
public float velocity;
public float tilt;
MoverBolt obj = new MoverBolt();
/* I made an object but it seems you are not supposed to create an object of class which is inheritance of MonoBehaviour */
void FixedUpdate()
{
float moveHorizontal = Input.GetAxis ("Horizontal");
float moveVertical = Input.GetAxis ("Vertical");
Vector3 movement = new Vector3 (moveHorizontal, 0.0f, moveVertical);
obj.rb.velocity = movement*velocity;
Vector3 current_position = obj.rb.position;
obj.rb.position = new Vector3 ( Mathf.Clamp(current_position.x,boundary.xMin,boundary.xMax),
0.0f,
Mathf.Clamp(current_position.z, boundary.zMin, boundary.zMax)
);
obj.rb.rotation= Quaternion.Euler(0.0f,0.0f,obj.rb.velocity.x*-tilt );
}
}
Error You are trying to create a MonoBehaviour using the 'new' keyword. This is not allowed. MonoBehaviours can only be added using AddComponent().
Are there any alternatives ?
it's possible to call a Start() method from outside. just make it public.
public class MoverBolt : MonoBehaviour {
public void Start ()
{
Debug.Log("MoverBolt.Start() was called");
}
}
public class PlayerControl : MonoBehaviour {
[SerializeField]
private MoverBolt _moverBolt;
void Start ()
{
_moverBolt.Start();
}
}
The output in the console of this is
MoverBolt.Start() was called
MoverBolt.Start() was called
UPDATE 1
I would not recommend this, because the Start() method is called by your code and the game engine again.
When I need to make sure a MonoBehaviour is properly setup, before another class uses it. I replace the Awake/Start method with public void Initialize() method and call that from outside.
Very simple answer. You can't Access start () function from any other scripts.
Use "Instantiate". For example, you can create of prefab of the game object that you want to make a copy of and then use the prefab to generate the new objects.
public class ObjectFactory : MonoBehaviour()
{
public GameObject prefab; // Set this through the editor.
public void GenerateObject()
{
// This will create a copy of the "prefab" object and its Start method will get called:
Instantiate(prefab);
}
}

Unity 3D Instantiated Prefabs stop moving

I set up a pretty simple scene where a prefab is being instantiated every x seconds. I applied a transform.Translate on the instances in the Update() function. Everything works fine until a second object is spawned, the first one stops moving and all the instances stop at my translate value.
Here is my script, attached to an empty GameObject:
using UnityEngine;
using System.Collections;
public class Test : MonoBehaviour {
public GameObject prefab;
private Transform prefabInstance;
void spawnEnemy() {
GameObject newObject = (GameObject)Instantiate(prefab.gameObject, transform.position, transform.rotation);
prefabInstance = newObject.transform;
}
void Start() {
InvokeRepeating ("spawnEnemy", 1F, 1F);
}
void Update () {
if (prefabInstance) {
prefabInstance.transform.Translate (new Vector3(4,0,0) * Time.deltaTime);
}
}
}
Your movement is occuring on the prefabInstance object in your Update(), however, that object gets overwritten when the second instance is created, so only your last instantiated prefab will move.
You should consider splitting your code into 2 scripts, the first one to spawn the prefab, and the second script actually on the prefab to move it.
public class Test : MonoBehaviour {
public GameObject prefab;
void spawnEnemy() {
Instantiate(prefab, transform.position, transform.rotation);
}
void Start() {
InvokeRepeating ("spawnEnemy", 1F, 1F);
}
}
and put this script on your prefab:
public class Enemy : MonoBehaviour {
void Update () {
transform.Translate (new Vector3(4,0,0) * Time.deltaTime);
}
}

Categories

Resources