How to detect collision to stop player movement in Unity? - c#

I'm a beginner and I want to know how to make player stops movement when hitting an obstacle.
I tried this code but it shows that it's deprecated
public class Collision : MonoBehaviour
{
public PlayerMove move;
void onCollisionEnter (Collision info)
{
if (info.Collider.tag == "Obstacle")
{
move.enabled = false;
}
}
}

Be careful with methods in Unity, they start with an Uppercase.
OnCollisionEnter should start with an Uppercase to be recognized by Unity as the method called once per collision.
As scopolamin said, don't call your class Collision : you'd better rename it as well as your file, your class name and your file name must match in order to inherit from a MonoBehaviour.
I assume PlayerMove is the script you use as a character controller. Be sure your variable move has the right script attached.

You named your class Collision. The parameter info in the OnCollisionEnter method doesn't use UnityEngine.Collision but your own Collision class.
Change your class name Collision to something else:
public class Collision : MonoBehaviour
public class MyCollision : MonoBehaviour

Related

How to call a script component from a GameObject that is child to another GameObject, but from other GameObject?

In my unity project, I have a GameObject called "Spawn_manager", that has another Child GameObject called "Enemy_Container". The script of Spawn_Manager makes "Enemy" prefabs instantiate inside the "Enemy_Container". I am trying to acess the "Enemy" script(also named Enemy) from another script.
Anyone knows how I can get it?
I tried writing this:
private Enemy _enemy;
private void Start()
{
_enemy = GameObject.Find("Enemy").GetComponent<Enemy>();
}
But obviously it is not working, but I can't get it to work. Basically, I wanna the script, and the path would be Spawn_Manager>Enemy_Container>Enemy.
If you want to make the Enemy easily accessible you can add all spawned Enemy to static list. Like this:
public class Enemy : MonoBehaviour
{
public static List<Enemy> AllEnemy { get; private set; } = new List<Enemy>();
private void Awake()
{
AllEnemy.Add(this);
}
private void OnDestroy()
{
AllEnemy.Remove(this);
}
}
Using Find is demanding and not a reliable operation. If you will have any other GameObjects with name Enemy it will found them instead of desired one.
in this case i think that problem is that after instantiation prefab new GameObject have name in format $"{prefab.name}(Clone)".

The local function 'OnTriggerEnter2D' is declared but never used

I don't know how to fix it. It's a 2D game. When you collide with the box, it should load/teleport you to the next scene, but it doesn't.
I tried everything on the internet and it didn't work.
using UnityEngine;
using UnityEngine.SceneManagement;
public class VictoryZone : MonoBehaviour
{
public void LoadNextLevel()
{
void OnTriggerEnter2D(Collider2D collider)
{
SceneManager.LoadScene(1);
}
}
}
I expect it to teleport me to my next level.
It looks like you nested the OnTriggerEnter2D() function inside of LoadNextLevel()? That's what the Local Function warning is referring to.
Those should be two separate functions, not one within the other. OnTriggerEnter2D() is a function of MonoBehavior; the MonoBehavior (VictoryZone) is what gets notified of the collision.
using UnityEngine.SceneManagement;
public class VictoryZone : MonoBehaviour {
public void LoadNextLevel() {
SceneManager.LoadScene(1);
}
void OnTriggerEnter2D(Collider2D collider) {
LoadNextLevel();
}
}
Note: you might also need to check the GameObject associated with collider to make sure that it's a player, and not an enemy or something (if, hypothetically, you had enemies or projectiles or other objects with colliders moving into the victory zone).

Unity3D - Abstract Class, Monobehaviour functionality

PREAMBLE
So I've been floating this question around on the Unity Answers forum for the past couple of weeks without a single reply. It seems to me that it would be a relatively straight forward question so I was wondering if anyone here might be able to help me with it in lieu of an answer over there.
So I have a bit of a dilemma.
GOAL
I want to use an inheritance structure for guns in my game. I want to make an abstract class (Gun) and then have subclasses of Gun (Laser, Rifle, RocketLauncher) which inherit from it and then create specific instances of these weapons. At the moment I'm doing this as an abstract class because there's a large variance between the way different subclasses of Gun implement the Shoot() function. (i.e. A rocket launcher will instantiate X Rocket GameObjects whereas a laser will probably use raycasting to determine an instant hit).
Furthermore, I would like to be able to have a List of Guns in the Players inventory and don't want to have to add and remove Scripts from my Player dependant on their active weapon. It's just nice for me if I can construct them in the following fashion:
Rifle ActiveWeapon = new Rifle(parameters);
I also don't want to have a finite number of weapons available to the player but want to be able to generate them at runtime (as drops or crafted for example) so I also don't want to write a fixed number weapon scripts.
ISSUE
The issue I'm encountering is that I want to be able to utilise some of the methods which are derivative of MonoBehaviours for example :
public override void Shoot ()
{
if (CanShoot)
{
StartCoroutine(Cooldown());
Rigidbody bullet = Rigidbody.Instantiate(BulletPrefab, transform.position, transform.rotation);
... // Addforce etc.
...
}
}
public IEnumerator Cooldown()
{
CanShoot = false;
yield return new WaitForSeconds (FireRate);
CanShoot = true;
}
Obviously since this isn't a MonoBehaviour class I can't use functions such as Instantiate to create bullets or WaitForSeconds to stagger them.
How should I tackle this issue?
You can have an abstract class that inherits from MonoBehaviour, the following works fine:
public abstract class AbstractClass : MonoBehaviour
{
protected abstract void pouet();
}
public class InheritClass : AbstractClass
{
// Use this for initialization
void Start ()
{
StartCoroutine(pouetCoroutine());
}
protected override void pouet()
{
Debug.Log("pouet");
}
private IEnumerator pouetCoroutine()
{
yield return null;
pouet();
}
}
If you don't want your abstract class to be in a GameObject, you could use an external gameobject to manage the instanciation with an object pooling system.
About the coroutines, you could use a coroutine engine that starts and stop them. You only need to have a dictionary and a public function to start the coroutine and keep an id as a key to access it if you need to stop it later.
private startcoroutine(int id, IEnumerator ienum)
{
Coroutine c = StartCoroutine(ienum);
dictionary.Add(id, c);
}

How to instantiate prefab after specified prefab have been instantiated?

I have Enemy.cs to stochastically instantiate enemies.
Then I want to get a hero.cs to instantiate heroes.
The requirement is to instantiate the hero following the corresponding enemy.
For example, find enemy_01 in scene, then instantiate hero_01.
Find enemy_02 in scene, then instantiate hero_02.
Without enemy_03, hero_03 should not be instantiated.
Even harder, I want to choose which hero to be instantiated.
For example, with enemy_01 in scene, 80 % chance to instantiate hero_01, 20 % chance to instantiate hero_02.
With enemy_02 in scene, 50 % chance to instantiate hero_02, 50 % chance to instantiate hero_03.
But without enemy_03, hero_03 can not be instantiated.
Could you give me an idea or thinking?
My Hero.cs
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class Hero_list : MonoBehaviour
{
[System.Serializable]
public class Hero
{
public GameObject Hero_prefab;
public GameObject Need_prefab;
}
public List <Hero> Heroes = new List <Hero> ();
public static Hero_list instance;
public void findEnemy()
{
GameObject[] respawns = GameObject.FindGameObjectsWithTag("Enemy");
foreach (GameObject respawn in respawns)
{
Debug.Log(respawn);
}
}
void Update ()
{
findEnemy();
}
}
One possibility is to let the enemy call findEnemy() of Hero.cs when an it is spawned, either in its Start() or OnAwake() method. Then spawn the hero.
Since these are just normal functions, you can execute whatever logic you want in them, thus being able to chain instantiation of game objects.

Instantiating prefabs from another script (The prefab you want to instantiate is null)

So I have an enemy spawner with a method to instantiate prefabs working just fine. Simplified:
public class EnemySpawner : MonoBehaviour {
public GameObject EnemyPrefab;
public void setEnemies()
{
Instantiate (EnemyPrefab, enemyPos, rotation);
}
void Start()
{
setEnemies();
}
}
This works fine. But it doesnt work when I call it from a different script:
public class Player : MonoBehaviour {
public EnemySpawner enemyspawner;
void Update(){
if (Input.GetMouseButtonDown (0))
{
enemyspawner= new EnemySpawner();
enemyspawner.setEnemies();
}
}
I keep getting this error:
ArgumentException: The prefab you want to instantiate is null.
What am I doing wrong?
Edit:
So I figured that I could not create a Monobeaviour by using the New keyword .I changed it to:
enemyspawner = gameObject.AddComponent<EnemySpawner> ();
enemyspawner.setEnemies();
But that still wont work.
I just read your comment about changing:
new to enemyspawner = gameObject.AddComponent<EnemySpawner>();
However, you did not properly solve the problem, you only made a workaround that won't work because your prefab, public GameObject EnemyPrefab;, won't be set.
With your new code gameObject.AddComponent<EnemySpawner>(); You are attaching a script to the Player GameObject, this will bring you problems in the future.
My Suggestion
Create an Empty GameObject and attach EnemySpawner to it and name it EnemySpawnerObj.
Then to call the function setEnemies() from another class you do this:
EnemySpawner spwner = GameObject.Find("EnemySpawnerObject").GetComponent<EnemySpawner>();
spwner.setEnemies();
So what you are doing is looking through your scene for the GameObject named EnemySpawnerObject then you get the component named EnemySpawner and then you can call that class instance.

Categories

Resources