Why is Instantiate only cloning four times? - c#

My issue here is that my object (a 500 long cube with a trigger on top) is only cloning four times with Instantiate(). Can anyone explain as to why? Is there a limit to how far you can clone items?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class groundGen : MonoBehaviour
{
public Transform player;
public Object ground;
public Transform groundLoc;
public int distance = 500;
public void OnTriggerEnter(Collider checkPass)
{
if (checkPass.tag == "checkpoint")
{
Instantiate(ground, groundLoc.position + new Vector3(0, 0, distance), groundLoc.rotation);
distance += 500;
}
}
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
}

There is no real limit.
But:
there is some inaccuracy due to floating point numbers, if your coordinates get really big.
Your meshes could get clipped by Camera. Log your Instantiate Calls and check hierarchy in Playmode. Increase Cameras far-plane if needed.

Related

I'm trying to add multiple camera switches to a vehicle in Unity and I am not sure how to code it

My project is from the "Create with Unity" tutorial unit 1 with a simple vehicle moving down a road. I originally had 1 camera which worked, but when I changed the code to work with multiple cameras I couldn't get the compiler to work.
The 3 cameras are supposed to display different angles of the tank while controlling the vehicle. I assume something is wrong with how I wrote the FollowPlayer.cs "void LateUpdate()" method, but I don't know how to make it work. It all went wrong when I changedthe FollowPlayer class from 1 cam to 3 cams.
The picture shows the unity visuals and all relevant class coding is below.
I'm new to unity and c#, so any help would be appreciated!
MY CAM SWITCH CLASS
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CamSwitch : MonoBehaviour
{
public GameObject cam1;
public GameObject cam2;
public GameObject cam3;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
if(Input.GetButtonDown("Switch1"))
{
cam1.SetActive(true);
cam2.SetActive(false);
cam3.SetActive(false);
}
if (Input.GetButtonDown("Switch2"))
{
cam1.SetActive(false);
cam2.SetActive(true);
cam3.SetActive(false);
}
if (Input.GetButtonDown("Switch3"))
{
cam1.SetActive(false);
cam2.SetActive(false);
cam3.SetActive(true);
}
}
}
THE CLASS I THINK I MESSED UP
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class FollowPlayer : MonoBehaviour
{
public GameObject player;
public Vector3 offset1= new Vector3(0, 5, -7);
public Vector3 offset2 = new Vector3(0, 3.83, -7);
public Vector3 offset3 = new Vector3(0, 7.68, -11.8);
public GameObject cam1;
public GameObject cam2;
public GameObject cam3;
cam1.SetActive(true)
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void LateUpdate()
{
if (cam1.SetActive(true))
{
transform.position = player.transform.position + offset1;
}
if (cam2.SetActive(true))
{
transform.position = player.transform.position + offset2;
}
if (cam3.SetActive(true))
{
transform.position = player.transform.position + offset3;
}
}
}
First: remove the line cam1.SetActive(true) under public GameObject cam3;. Its missing a semicolon and it must be placed in a function scope anyway, not in class declaration scope.
Second: this statement (and the other two) if (cam1.SetActive(true)) cant work because SetActive does not return a bool value. You probably wanted if (cam1.activeSelf).
You may spend some time improving your knowledge C# coding basics in Unity

Make object follow rotation with very little difference

I am making my object follow the rotation of another object. I want my object to rotate with very little difference, that is, from its current rotation it should not rotate completely with the other object.
There should be a difference u pto its rotation such that it should rotate 10% of what the main object rotates. How do I do this?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class FollowRotationWithLimit : MonoBehaviour {
public GameObject objectToFollow;
// Start is called before the first frame update
void Start () {
}
// Update is called once per frame
void Update () {
this.transform.eulerAngles = new Vector3 (this.transform.eulerAngles.x, objectToFollow.transform.eulerAngles.y, this.transform.eulerAngles.z);
}
}
I am not able to get that logic of creating that difference.
I would rather call it FollowRotationWithFactor then and simply use a multiplier
public class FollowRotationWithFactor : MonoBehaviour
{
public GameObject objectToFollow;
public float factor = 0.1f;
// Update is called once per frame
void Update ()
{
var eulerAngles = transform.eulerAngels;
eulerAngles.y = objectToFollow.transform.eulerAngles.y * factor;
transform.eulerAngles = eulerAngles;
}
}

Unity 2D - Attack system only works while moving

I've recently started coding on Unity, trying to make a game. So long it's been fine, but I faced a problem.
I've implemented a script for the Attack System:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class AttackDamage : MonoBehaviour
{
private float attackDamage = 20;
private void OnTriggerEnter2D(Collider2D other)
{
if (other.GetComponent<Health>() != null)
{
Health health = other.GetComponent<Health>();
health.TakeDamage(attackDamage);
}
}
}
And I also implemented one for the Health System:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
public class Health : MonoBehaviour
{
public Image healthBar;
public float healthAmount = 100;
private void Update()
{
if (healthAmount <= 0)
{
SceneManager.LoadScene(0);
}
}
public void TakeDamage(float Damage)
{
healthAmount -= Damage;
healthBar.fillAmount = healthAmount / 100;
}
public void Healing(float healPoints)
{
healthAmount += healPoints;
healthAmount = Mathf.Clamp(healthAmount, 0, 100);
healthBar.fillAmount = healthAmount / 100;
}
}
And it works prety well.
But as you read on the title, the attack only actually works right after I move. If I try to attack while I'm not moving, the attackArea appears on the scene, but doesn't deal damage. And i can't figure out why.
Do you have any idea on what could be the problem?
Here there's also a video of what actually happens, in the game:
https://drive.google.com/drive/folders/1BTYTNz_yzus-eRLnjsgB0hsYLU5sQm2k?usp=sharing
I have no idea on how to solve this problem, since I've copied the code from a source online, which actually works prorperly.
The code is exactly the same, apart form the script for the Health System, which is not shown on the video, but which also shouldn't make that much of a difference.
So i really don't know how to handle this.
Thanks for the help :)
If you are looking to deal continuous damage while any health-character is in the trigger, use OnTriggerStay2d instead.
Otherwise, if you are looking to deal damage when the user presses a button, you can do the following:
Have a hit-box collider that stores all enemy in range. (By adding enemy to a list when it enters the hit-box, and removing them from list when they exit.)
When the attack is triggered, fetch all enemy in the list from 1. and deal damage to all.
Code-wise, looks something like this:
public class AttackDamage : MonoBehaviour
{
private HashSet<Health> inRange = new HashSet<Health>();
private float attackDamage = 20;
private void OnTriggerEnter2D(Collider2D other)
{
if (other.GetComponent<Health>() != null)
{
// Add to set of characters that are in range of attack
inRange.Add(other.GetComponent<Health>());
}
}
private void OnTriggerExit2D(Collider2D other)
{
var charHealth = other.GetComponent<Health>();
if (charHealth != null) {
// Remove, since it exit the range of the attacking character.
inRange.Remove(charHealth);
}
}
// Call this function whenever you want to do damage to all characters in range.
public void Attack(){
foreach(var character in inRange){
character.TakeDamage(attackDamage);
}
}
}
Then somewhere else... (example, in your player.)
public class YourPlayer {
// ...
// Inspector reference to the hitbox
[SerializeField]
private AttackDamage attackHitbox;
private void Update(){
// Attack when button is pressed (or something).
if (Input.GetKeyDown(KeyCode.A)) {
attackHitbox.Attack();
}
}
// ...
}
Finally, if you are looking to deal damage at specific points in an animation, the term you should search for is Key-Frame. Look for a tutorial on Animation, then Key-Frame.
Once you learn about it, you can use the above mentioned method, but call the damage script on your desired key-frames.

Unity (C#) - How do I single out GameObject being detected by Raycast in a destroy / respawn system

I'm trying to make a Destroy gameobject, wait x seconds, respawn gameobject system. I have 2 scripts and I'm destorying then instantiating it again. I want to use multiples of the same prefab called "Breakable" but have only the one I'm aiming at being destroyed. Similar to games like Minecraft, aim and only the aimed at the block is destroyed.
BlockBreakItem script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BlockBreakItem : MonoBehaviour
{
RaycastHit hit;
int layerMask = 1;
public GameObject breakableObject;
public bool isObjectDestoryed = false;
public int score = 0;
// Update is called once per frame
void Update()
{
breakableDetection();
}
void breakableDetection()
{
Ray rayLocation = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(rayLocation, out hit, 1000, layerMask))
{
print("Detected");
if (Input.GetKey(KeyCode.Mouse0))
{
breakableObject = GameObject.Find("Breakable");
Destroy(breakableObject);
isObjectDestoryed = true;
score = score +1 ;
}
}
}
}
RespawnBrokenObject script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class RespawnBrokenObject : MonoBehaviour
{
private BlockBreakItem BlockBreakItem;
public GameObject breakablePrefab;
// Start is called before the first frame update
void Start()
{
BlockBreakItem = GameObject.FindObjectOfType<BlockBreakItem>();
}
// Update is called once per frame
void Update()
{
if (BlockBreakItem.isObjectDestoryed == true)
{
Invoke("respawnObject", 5.0f);
BlockBreakItem.isObjectDestoryed = false;
}
}
void respawnObject()
{
GameObject tempObjName = Instantiate(breakablePrefab);
tempObjName.name = breakablePrefab.name;
BlockBreakItem.breakableObject = tempObjName;
}
}
I hope the code isn't too messy! Always worried it won't be understood xD
Fortunately it's easy and basic in Unity!
You don't do this:
breakableObject = GameObject.Find("Breakable");
The good news is the cast will tell you what object you hit! Great, eh?
It's basically:
hit.collider.gameObject
You can use hit.collider.gameObject.name in a Debug.Log for convenience.
It's that easy!
Note you then (if you need it) get your component on that object with something like .GetComponent<YourBreakishBlock>()... easy.
Note that you can CHECK if the object hit, is one of the "YourBreakishBlock" objects, by simply checking if that component is present.
Note simply google something like "unity physics raycast out hit, which object was hit ?" for endless examples,
https://forum.unity.com/threads/getting-object-hit-with-raycast.573982/
https://forum.unity.com/threads/changing-properties-of-object-hit-with-raycast.538819/
etc.
--
Make this simple class:
public class ExamplePutThisOnACube: MonoBehavior
{
public void SAYHELLO() { Debug.Log("hello!"); }
}
Now put that on SOME cubes but NOT on OTHER cubes.
In your ray code:
ExamplePutThisOnACube teste =
hit.collider.gameObject.GetComponent<ExamplePutThisOnACube>();
and then check this out:
if (teste != null) { teste.SAYHELLO(); }
Now run the app and try pointing at the various cubes!

Give every prefab his own speed

Is was building a star background simulation for a spaceshooter game in UNITY3D.
In c# i built The Instantitiation of prefabs which look like dots. While the generation of multiple dots on random spots on the x-axis go perfectly i wanted to add one thing.
Random speed. The problem is that i don't know how to give every prefab his own speed en keep it instead of getting overwritten by the next randomnization.
backgroundloop.cs
using UnityEngine;
using System.Collections;
public class backgroundloop : MonoBehaviour {
public GameObject star;
public float spawnTime;
private GameObject starPrefab;
private float timestamp;
//public float hoogte = Random.Range(-1.01f,1.1f);
//public float rotationPrefab = transform.localEulerAngles.z;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
if (Time.time > timestamp) {
starPrefab = Instantiate
(star, new Vector3(7,Random.Range(-5.0f,5.0f),0),
Quaternion.Euler(0, 0, 0)) as GameObject;
timestamp = Time.time + spawnTime;
}
}
}
And the problem is in this script:
prefabMovement.cs
using UnityEngine;
using System.Collections;
public class prefabMovement : MonoBehaviour {
float speed = Random.Range (-3f, -0.1f);
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
transform.Translate (new Vector3(-1f,0,0) * Time.deltaTime);
if (transform.position.x < -6.8) {
Destroy (this.gameObject);
}
}
}
Huh? So the speed is overwritten and eventually ends up being the same on all instantiated prefabs?
Maybe it helps if initialize the speed variable inside the Start method.

Categories