I made this code where I have 8 objects and each object has this script, where between a random time interval the objects drop randomly
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class cylinderFallv2 : MonoBehaviour
{
private Rigidbody temp;
// Start is called before the first frame update
void Start()
{
temp = GetComponent<Rigidbody>();
StartCoroutine(waitTime());
}
public IEnumerator waitTime() {
temp.useGravity = false;
float wait_time = Random.Range (3.0f;, 12.0f;);
yield return new WaitForSeconds(wait_time);
temp.useGravity = true;
}
}
what he intended was for the objects to fall one by one with an interval between them in a random order. any ideas?
If you want to control several objects, and they have some relation to each other, it is usually best to have one script on any GameObject, and let that script handle the other objects. The following example script can be placed on any GameObject.
using System.Collections;
using System.Linq;
using UnityEngine;
public class RandomFall : MonoBehaviour
{
public Rigidbody[] rigidbodies;
public float minTime = 3.0f;
public float maxTime = 12.0f;
private void Start()
{
foreach (Rigidbody rigidbody in rigidbodies)
rigidbody.useGravity = false;
StartCoroutine(dropRandomly());
}
public IEnumerator dropRandomly()
{
foreach (var rigidbody in rigidbodies.OrderBy(r => Random.value))
{
float wait_time = Random.Range(minTime, maxTime);
Debug.Log($"Waiting {wait_time:0.0} seconds...");
yield return new WaitForSeconds(wait_time);
Debug.Log($"Dropping {rigidbody.name}...");
rigidbody.useGravity = true;
}
Debug.Log("All dropped!");
}
}
You then have to add references to the objects you want to drop in the scene editor. It should look something like this (I have added four cylinders). Note that the objects you try to add must of course already have a Rigidbody component on them.
Related
enter code hereHello im trying to make a laser but the collider as a weird offset from the collider. I tried moving some object out of the parent but it didnt changed anything. The only place where it works properly is 0,0,0.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Laser : MonoBehaviour
{
[SerializeField] public float defDistanceRay = 100;
public Transform laserFirePoint;
public LineRenderer m_lineRenderer;
public Transform m_transform;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
ShootLaser();
}
void ShootLaser(){
if(Physics2D.Raycast(m_transform.position, transform.right)){
RaycastHit2D _hit = Physics2D.Raycast(laserFirePoint.position, transform.right);
Draw2DRay(laserFirePoint.position, _hit.point);
}
else{
Draw2DRay(laserFirePoint.position, laserFirePoint.transform.right * defDistanceRay);
}
}
void Draw2DRay(Vector2 startPos, Vector2 endPos) {
m_lineRenderer.SetPosition(0, startPos);
m_lineRenderer.SetPosition(1, endPos);
}
}
This code made it work properly whitout before I added this code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Laser_collision : MonoBehaviour
{
public LineRenderer LineRenderer;
public EdgeCollider2D collider;
void Update(){
int pointcount = LineRenderer.positionCount;
Vector2[] points = new Vector2[pointcount];
for(int i = 0; i < pointcount; i++){
points[i] = LineRenderer.GetPosition(i);
}
collider.points = points;
}
}
Thank you for your time
So, in Unity I am trying to load the player's position from PlayerPrefs.
LOAD FUNCTION
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using System.IO;
using UnityEngine.UI;
using CI.QuickSave;
public class RELoadSave : MonoBehaviour
{
public GameObject Player;
public float x, y, z;
private bool saving = false;
private int Mode = 0;
private Vector3 coordsem;
private int count;
protected FileInfo theSourceFile = null;
protected StreamReader reader = null;
protected string text = " "; // assigned to allow first line to be read below
public Button btn;
void Start()
{
x = PlayerPrefs.GetFloat("x");
y = PlayerPrefs.GetFloat("y");
z = PlayerPrefs.GetFloat("z");
Vector3 LoadPosition = new Vector3(x, y, z);
Player.transform.position = LoadPosition;
}
private void Awake()
{
}
void Update()
{
}
public void ResetScene()
{
SceneManager.LoadScene(SceneManager.GetActiveScene().name);
}
}
SAVE FUNCTION
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using System.IO;
using TMPro;
using UnityEngine.UI;
using CI.QuickSave;
public class SaveGame : MonoBehaviour
{
public float coordse;
public float x, y, z;
public GameObject Player;
// Start is called bsefore the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
public void SaveGameCore()
{
x = Player.transform.position.x;
y = Player.transform.position.y;
z = Player.transform.position.z;
PlayerPrefs.SetFloat("x", x);
PlayerPrefs.SetFloat("y", y);
PlayerPrefs.SetFloat("z", z);
}
}
Things to note:
these functions are NOT called inside the player
running Unity 2019
This is meant to be applicable to a 3d FPS game, taht is what the code is for not a 2d game. BUT I am confused, but I probally made a simple mistake. If it is not replacatable, I can upload small assets from the game. It should be working but it isn't. The player also can only collide with 2d box coliders if that helps.
I checked your code and everything works fine
public float x,y,z;
public GameObject Player;
public Vector3 LoadPosition;
public void Save()
{
x = Player.transform.position.x;
y = Player.transform.position.y;
z = Player.transform.position.z;
PlayerPrefs.SetFloat("x_", x);
PlayerPrefs.SetFloat("y_", y);
PlayerPrefs.SetFloat("z_", z);
}
public void Load()
{
x = PlayerPrefs.GetFloat("x_");
y = PlayerPrefs.GetFloat("y_");
z = PlayerPrefs.GetFloat("z_");
LoadPosition = new Vector3(x, y, z);
Player.transform.position = LoadPosition;
}
The problem may be related to the method of calling save or laod
Perhaps the problem is with the version of the unity you have, this is an unlikely possibility
Anyway, you can do without PlayerPrefs by saving the player data (Positino) in a text file inside the folder
Take a look at this reference for saving and Load
At the moment I am programming a Unity 2D game. When the game is running the cars start moving and respawn continuously. I added kind of a life system to enable the possibility to shoot the cars. My issue is that my health bar as well as my score board need references to the objects they refer to, but I am unable to create a reference to an object which is not existing before the game starts. Another issue is that I don't know how to add a canvas to a prefab in order to spawn it with the cars continuously and connect them to the car. Is there a way to avoid these conflicts or how is it possible to set the references into prefabs. I will add the code of the spawner, the car and the the scoreboard. Already thank you in advance
Spawner:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Spawner : MonoBehaviour
{
public GameObject carPrefab;
public GameObject enemyCarPrefab;
public GameObject kugel;
public float respawnTime = 10.0f;
public int counterPlayer1=0;
public int counterPlayer2=0;
public int counterEnergy=0;
// Use this for initialization
void Start () {
StartCoroutine(carWave());
}
private void spawnPlayerCars(){
GameObject a = Instantiate(carPrefab) as GameObject;
a.transform.position = new Vector2(-855f, -312.9426f);
counterPlayer1++;
}
private void SpawnEnemyCars(){
GameObject b = Instantiate(enemyCarPrefab) as GameObject;
b.transform.position = new Vector2(853,-233);
counterPlayer2++;
}
private void SpawnEnergy(){
GameObject c = Instantiate(kugel) as GameObject;
c.transform.position = new Vector2(-995,-192);
counterEnergy++;
}
IEnumerator carWave(){
while(true){
yield return new WaitForSeconds(respawnTime);
if(counterPlayer1<3){
spawnPlayerCars();
Debug.Log(counterPlayer1);
}
if(counterPlayer2<3){
SpawnEnemyCars();
Debug.Log(counterPlayer2);
}
if(counterEnergy<3){
SpawnEnergy();
}
}
}
}
Car:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EnemyCar : MonoBehaviour
{
public float speed = 3f;
int zählerAuto1=0;
private Vector2 screenBounds;
public AnzeigePunktzahlPlayer2 points;
public Spawner sp;
public int maxHealth=100;
public int currentHealth;
public HealthBar healthbar;
void Start () {
screenBounds = Camera.main.ScreenToWorldPoint(new Vector2(Screen.width, Screen.height));
points= GetComponent<AnzeigePunktzahlPlayer2>();
sp= GetComponent<Spawner>();
currentHealth=maxHealth;
healthbar.SetMaxHealth(maxHealth);
}
void Update()
{
Vector2 pos = transform.position;
if(pos.x>-855f){
pos = transform.position;
pos.x-= speed* Time.deltaTime;
transform.position=pos;
zählerAuto1++;
}else{
points.counter++;
Debug.Log(points.counter);
sp.counterPlayer2--;
Debug.Log(sp.counterPlayer2);
Destroy(this.gameObject);
}
}
private void OnCollisionEnter2D(Collision2D other) {
if (other.collider.tag=="Kugel"){
takeDamage(40);
//sp.counterPlayer2--;
if(currentHealth<=0)
{
Destroy(this.gameObject);
}
}
}
public void takeDamage(int damage){
currentHealth-= damage;
healthbar.SetHealth(currentHealth);
}
public void getHealed(int heal){
currentHealth+= heal;
healthbar.SetHealth(currentHealth);
}
}
Scoreboard(one part of it(the other one is almost the same)):
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;
public class AnzeigePunktzahlPlayer1 : MonoBehaviour
{
public int counter;
public TextMeshProUGUI textPlayer1;
void Start()
{
// counter=0;
textPlayer1= GetComponent<TextMeshProUGUI>();
}
// Update is called once per frame
void Update()
{
textPlayer1.SetText( counter.ToString());
}
}
You could make the health bars and the canvas children of the Car prefab and have them spawn together.
in my Unity scene I'm trying to activate a portal animation when you pick up all the coins on that level, but the problem is that my portal script does not detect when the coin counter value is equal to 6 (that's the total number of coins in that level).
I have this script which is the script that is attached to the coins and increases the coin counter value.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MonedaScript2 : MonoBehaviour
{
public GameObject moneda;
public AudioClip clip;
public Vector3 PosicionMoneda;
public void Update ()
{
transform.Rotate (0, 90 * Time.deltaTime, 0);
}
public void OnTriggerEnter(Collider other)
{
if (other.name == "Player")
{
AudioSource.PlayClipAtPoint(clip, PosicionMoneda, 1f);
AparecerPortalNivel9.ContadorMonedas += 1;
Destroy(moneda);
}
}
}
And then i have the portal script which sould detect ewhen you pick all the coins. It is attached to the PanelPortal gameobject.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class AparecerPortalNivel9 : MonoBehaviour
{
public Animator anim;
public GameObject PanelPortal;
//public ScoringSystem SS;
public bool DeberiaAparecer = true;
public static int ContadorMonedas;
void Start()
{
//SS = GameObject.FindGameObjectWithTag("SistemaDeScore").GetComponent; ScoringSystem();
PanelPortal.gameObject.SetActive(false);
}
void Update()
{
if (ContadorMonedas == 6f)
{
Debug.Log("FuncionaHostia");
PanelPortal.gameObject.SetActive(true);
anim.SetBool("Aparecer",true);
DeberiaAparecer = false;
}
}
}
Could someone help me on what should i do so my portal script detects when the coins picked up are 6 and then run all the functions inside the IF method?
Thanks everyone
A MonoBehaviour's Update will never run while the gameobject it is on is disabled.
Because AparecerPortalNivel9 is attached to PanelPortal, when you do this you are preventing the Update method from being called:
PanelPortal.gameObject.SetActive(false);
The easiest solution here is to move AparecerPortalNivel9 to a different gameobject.
I want to know how I can get a reference to a particular function on any another script through the unity inspector for adding it to a on-click listener of a dynamically instantiated button. I tried a public UnityEvent to get reference to the functions (just like in the onclick of a static button) but I am unsure how to add it to the on-click listener(button.onClick.AddListener(functionName)) as a listener looks for a action.
Is there anything I am missing out ? Or is there any other approach to this?
Thanks.
This is the idea -
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;
public class DynamicButton : MonoBehaviour
{
public Button MainButton;
public GameObject ButtonPrefab;
[System.Serializable]
public class ButtonInfo
{
public Sprite sprite;
public UnityEvent ButtonEvent; //take reference to a particular function
}
public ButtonInfo[] ButtonCount;
void Start()
{
PlaceButtons();
}
void PlaceButtons()
{
int NoButton = ButtonCount.Length;
for (int i = 0; i < NoButton; i++)
{
Vector3 newPos = new Vector3(i*10, i*10,0);
GameObject go = Instantiate(ButtonPrefab, newPos, Quaternion.identity);
go.GetComponent<Image>().sprite = ButtonCount2To6[i].sprite;
go.GetComponent<Button>().onClick.AddListener(); //This is where I want to add the particular function that i want to execute when the button is clicked
go.transform.parent = MainButton.transform;
go.transform.localPosition = newPos;
}
}
}
What you have to do is Invoke the event instead of adding it to the onClick event. You don't have to find out / copy the listeners of each UnityEvent but instead invoking the UnityEvent is enough. The UnityEvent than calls all its listeners you assigned e.g. in the Inspector. This can be done by a simple lambda function:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;
public class DynamicButton : MonoBehaviour
{
public Button MainButton;
public GameObject ButtonPrefab;
[Serializable]
public class ButtonInfo
{
public Sprite sprite;
public UnityEvent ButtonEvent; //take reference to a particular function
}
public ButtonInfo[] ButtonCount;
private void Start()
{
PlaceButtons();
}
private void PlaceButtons()
{
int NoButton = ButtonCount.Length;
for (int i = 0; i < NoButton; i++)
{
Vector3 newPos = new Vector3(i*10, i*10, 0);
GameObject go = Instantiate(ButtonPrefab, newPos, Quaternion.identity);
// What is ButtonCount2To6?? It probably should rather be ButtonCount[i] ?
go.GetComponent<Image>().sprite = ButtonCount2To6[i].sprite;
// since the lambda will have no acces to i you have to get the reference to the according ButtonInfo first
var accordingButtonInfo = ButtonCount[i];
// Add the Invoke call as lambda method to the buttons
go.GetComponent<Button>().onClick.AddListener(() => {
accordingButtonInfo .ButtonEvent.Invoke();
});
go.transform.parent = MainButton.transform;
go.transform.localPosition = newPos;
}
}
}
see also this post