How to instantiate two different Charaters using Photon Unity 3D - c#

I am making Third person multiplayer game with unity and Photon i can't get the Instantiating of players right both players are sometimes instantiating the same avatar or sometimes there camera Mix up. I have used Cinemachine Virtual camera and Cinemachine brain on main camera
My Hierarchy
Player Prefeb:
Cinemachine Virtual Cam:
Cinemachine brain cam:
This is my script that is responsible for intantiating players
using System.Collections;
using System.Collections.Generic;
using System.IO;
using Photon.Pun;
using UnityEngine;
public class PlayerInstantiator : MonoBehaviour
{
PhotonView PV;
bool spawnPoint1 = true;
bool spawnPoint2 = true;
public GameObject player1;
public GameObject player2;
public Transform sp1;
public Transform sp2;
private void Update()
{
Debug.Log(CheckPlayers());
if (CheckPlayers() == 1 && spawnPoint1 == true)
{
spawnPoint1 = false;
SpawnMasterPlayer();
}
else if (CheckPlayers() == 2 && spawnPoint2 == true)
{
// SpawnMasterPlayer();
SpawnPlayer2();
spawnPoint2 = false;
}
}
private void SpawnMasterPlayer()
{
if (PV.IsMine)
{
CreateController(player1.name, sp1);
}
}
private void SpawnPlayer2()
{
if (!PV.IsMine)
{
CreateController(player2.name, sp2);
}
}
private int CheckPlayers()
{
return PhotonNetwork.CurrentRoom.PlayerCount;
}
private void Awake()
{
PV = GetComponent<PhotonView>();
}
void CreateController(string name, Transform sp)
{
PhotonNetwork.Instantiate(name, sp.position, Quaternion.identity);
}
}
It takes two spawn points and players Prefeb all have photon View attached but still i cant figure it out
It should intantiate two differnt Avatars and make their camers function properly

Related

Instantiated prefab is not working as expected but when the prefab is put on the scene then everything runs as expected

I have a script attached to a prefab and the script is :
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class destroyer : MonoBehaviour
{
Circles circles;
CircleCollider2D collider1;
Collider2D collider2;
private void Start()
{
circles = FindObjectOfType<Circles>();
}
private void OnEnable()
{
collider1 = gameObject.transform.GetChild(0).GetComponent<CircleCollider2D>();
collider2 = gameObject.transform.GetChild(1).GetComponent<Collider2D>();
}
private void Update()
{
if (transform.position.y < 2)
{
Destroy(gameObject);
circles.instantiator();
}
}
void OnTriggerStay2D(Collider2D other)
{
if (collider1.bounds.Contains(other.bounds.max) && collider1.bounds.Contains(other.bounds.min))
{
if (other.bounds.Contains(collider2.bounds.max) && other.bounds.Contains(collider2.bounds.min))
{
if (transform.position.y > 3)
{
Destroy(other.gameObject);
Destroy(gameObject);
circles.instantiator();
}
}
}
}
}
When I instantiate the prefab the if condition is never running even if the condition is true.
But when I put the prefab on the scene and play the game then this if condition is running fine according to the condition. I am not able to figure out what is the problem in this.
Did you add the children of the prefabs in order. The GameObject with the 2D circle collider should be first and the 2nd child should have a 2D collider.
Try:
collider1 = GetComponentInChildren<CircleCollider2D>();
collider2 = GetComponentInChildren<Collider2D>();

Object reference not set to an instance of an object C# Unity using Collider2D trigger

Just wondering if anyone could help me out with a small issue in my code. On line 60, there is an error essentially telling me what I am referencing to does not exist. To my knowledge it does, but I am very new to Unity. I am trying to create a random dungeon generator for a University project. My classes are below:
using System.Collections.Generic;
using UnityEngine;
public class RoomSpawner : MonoBehaviour
{
public int openingDirection;
//1 = need bottom door
//2 = need top door
//3 = need left door
//4 = need right door
//So for a room with a door on the right, you will type 3, as a left door is needed in the next room to connect the two rooms.
private RoomTemplates templates;
private int rand;
private bool spawned = false;
private Destroyer destroyer;
void Start()
{
templates = GameObject.FindGameObjectWithTag("Rooms").GetComponent<RoomTemplates>();
Invoke("Spawn", 0.1f);
}
void Spawn()
{
if (spawned == false)
{
rand = Random.Range(0, templates.bottomRooms.Length);
if (openingDirection == 1)
{
//Need to spawn room with BOTTOM door
Instantiate(templates.bottomRooms[rand], transform.position, templates.bottomRooms[rand].transform.rotation);
}
else if (openingDirection == 2)
{
//Need to spawn room with TOP door
Instantiate(templates.topRooms[rand], transform.position, templates.topRooms[rand].transform.rotation);
}
else if (openingDirection == 3)
{
//Need to spawn room with LEFT door
Instantiate(templates.leftRooms[rand], transform.position, templates.leftRooms[rand].transform.rotation);
}
else if (openingDirection == 4)
{
//Need to spawn room with RIGHT door
Instantiate(templates.rightRooms[rand], transform.position, templates.rightRooms[rand].transform.rotation);
}
spawned = true;
}
}
void OnTriggerEnter2D(Collider2D other)
{
if (other.CompareTag("Spawn Point"))
{
if (other.GetComponent<RoomSpawner>().spawned == false && spawned == false)
{
Instantiate(templates.closedRoom, transform.position, Quaternion.identity);
}
spawned = true;
}
}
}
using System.Collections.Generic;
using UnityEngine;
public class Destroyer : MonoBehaviour
{
void OnTriggerEnter2D(Collider2D other)
{
Destroy(other.gameObject);
}
}
This issue is causing the entry room to be blocked by closed rooms, which are meant to block exits out into the scene view. I have followed BlackThornProd's tutorial on this, but cannot figure out what I have done wrong. Here is a link to the tutorial.
Many thanks!
EDIT
Here I have included the RoomTemplates Class if it helps. Many Thanks!
using System.Collections.Generic;
using UnityEngine;
public class RoomTemplates : MonoBehaviour
{
public GameObject[] bottomRooms;
public GameObject[] topRooms;
public GameObject[] leftRooms;
public GameObject[] rightRooms;
public GameObject closedRoom;
}
Are templates a gameobject? If so, I think you can try something like this:
private GameObject templates;
void Start()
{
templates = GameObject.FindGameObjectWithTag("Rooms");
RoomTemplates Templates = templates.GetComponent<RoomTemplates>();
Invoke("Spawn", 0.1f);
}

Can't parent objects in unity for oculus quest grab script

preface: i am very new to c#, and this is an object grabbing script i have taken from a prefab and edited.
script goal: detect if a game object is in pickup distance. if it is, when the grip trigger is pressed, parent the object to the virtual hand. when the trigger is released, remove the parent relationship. Also, while the object is parented to the controller, if the B button is held, scale the object up, and if the A button is held, scale the object down, and reset the scale upon thumbstick click.
I can see when my controller collides with the game object, but when i press the designated button to parent the object, nothing seems to happen.
I'd really appreciate any help I could get with this script, as there might be a significant amount i'm doing wrong.
I should mention that I don't really need any sort of physics simulations, all i need is the ability to manipulate an object floating in space for viewing purposes.
Thanks in advance!
Here is my script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Grabber : MonoBehaviour
{
// Update is called once per frame
void Update()
{
OVRInput.Update();
if ((OVRInput.Get(OVRInput.Axis1D.SecondaryHandTrigger)) > 0.2f && CollidingObject)
{
GrabObject();
}
if ((OVRInput.Get(OVRInput.Axis1D.SecondaryHandTrigger)) < 0.2f && ObjectInHand)
{
ReleaseObject();
}
if (OVRInput.Get(OVRInput.Button.Two) && ObjectInHand)
{
ScaleUp();
}
if (OVRInput.Get(OVRInput.Button.One) && ObjectInHand)
{
ScaleDown();
}
if (OVRInput.Get(OVRInput.Button.SecondaryThumbstick) && ObjectInHand)
{
ScaleReset();
}
}
public GameObject CollidingObject;
public GameObject ObjectInHand;
public void OnTriggerEnter(Collider other)
{
if (other.gameObject.GetComponent<Rigidbody>())
{
CollidingObject = other.gameObject;
}
}
public void OnTriggerExit(Collider other)
{
CollidingObject = null;
}
private void GrabObject()
{
ObjectInHand = CollidingObject;
ObjectInHand.transform.SetParent(this.transform);
ObjectInHand.GetComponent<Rigidbody>().isKinematic = true;
}
private void ReleaseObject()
{
ObjectInHand.GetComponent<Rigidbody>().isKinematic = false;
ObjectInHand.transform.SetParent(null);
ObjectInHand = null;
}
Vector3 scaleChangeUp = new Vector3(0.01f, 0.01f, 0.01f);
Vector3 scaleChangeDown = new Vector3(-0.01f, -0.01f, -0.01f);
public void ScaleUp()
{
ObjectInHand.transform.localScale += scaleChangeUp;
}
public void ScaleDown()
{
ObjectInHand.transform.localScale += scaleChangeDown;
}
private void ScaleReset()
{
ObjectInHand.transform.localScale = Vector3.one;
}
}

Next Scene Not Loading

My problem is that when all the enemies are killed the scene that should be loaded is not loading. I did add the scene to the Build setting (it has an index of 3) but it is still not loading. The script I created is attached to an empty object and not directly to the sprite (is that okay?). Can someone tell me why the scene isn't loading? Thank you.
This image is for to show you the EnemySpawner empty object inspector
EnemySpawner Script :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class EnemySpawner : MonoBehaviour {
[SerializeField] GameObject EnemyPreFab;
[SerializeField] int MaxEnemies = 30;
[SerializeField] float EnemySpawnTime = 1.00001f;
[SerializeField] GameObject FirstWaypoint;
int CurrentNumOfEnemies = 0;
public LevelManager myLevelManager;
public int maximumnumberofhits = 0;
int timesEnemyHit;
IEnumerator SpawningEnemies()
{
while(CurrentNumOfEnemies <= MaxEnemies)
{
GameObject Enemy = Instantiate(EnemyPreFab, this.transform.position, Quaternion.identity);
CurrentNumOfEnemies++;
yield return new WaitForSeconds(EnemySpawnTime);
}
}
void Start()
{
StartCoroutine(SpawningEnemies());
timesEnemyHit = 0;
if (this.gameObject.tag == "EnemyHit")
{
CurrentNumOfEnemies++;
}
}
void OnCollisionEnter2D()
{
timesEnemyHit++;
if (timesEnemyHit == maximumnumberofhits)
{
CurrentNumOfEnemies--;
Destroy(this.gameObject);
}
if (CurrentNumOfEnemies == 0)
{
myLevelManager.LoadLevel("NextLevelMenu");
Debug.Log("LevelLoaded");
}
}
}
LevelManger script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class LevelManager : MonoBehaviour {
public void LoadLevel(string name)
{
print("Level loading requested for" + name);
SceneManager.LoadScene(name);
}
}
EnemyShooting Script :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EnemyShooting : MonoBehaviour {
[SerializeField] float EnemyLaserSpeed = 10f;
[SerializeField] float EnemyLaserFireTime;
[SerializeField] GameObject LaserBulletEnemyPreFab;
[SerializeField] int MaxNumberOfHits = 1;
int CurrentNumberOfHits = 0;
Coroutine FireCoroutine;
void OnTriggerEnter2D(Collider2D collider)
{
if(collider.gameObject.tag == "PlayerLaser")
{
if(CurrentNumberOfHits < MaxNumberOfHits)
{
CurrentNumberOfHits++;
Destroy(collider.gameObject);
Score.ScoreValue += 2;//The user will be rewarded 1 point
}
}
}
void DestroyEnemy()
{
if(CurrentNumberOfHits >= MaxNumberOfHits)
{
Destroy(gameObject);
}
}
private void Fire()
{
FireCoroutine = StartCoroutine(ShootContinuously());
}
void BecomeVisible()
{
Fire();
}
IEnumerator ShootContinuously()
{
while (true)
{
GameObject LaserBulletEnemy = Instantiate(LaserBulletEnemyPreFab, this.transform.position, Quaternion.identity) as GameObject;
LaserBulletEnemy.GetComponent<Rigidbody2D>().velocity = new Vector2(0, EnemyLaserSpeed);
EnemyLaserFireTime = Random.Range(0.5f, 0.9f);
yield return new WaitForSeconds(EnemyLaserFireTime);
}
}
// Use this for initialization
void Start () {
BecomeVisible();
}
// Update is called once per frame
void Update () {
DestroyEnemy();
}
}
EnemyPathing script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EnemyPathing : MonoBehaviour {
[SerializeField] List<Transform> WayPoints;
[SerializeField] float EnemyMovingSpeed = 5f;
int WayPointIndex = 0;
void EnemyMoving()
{
if (WayPointIndex <= WayPoints.Count - 1)
{
var TargetedPosition = WayPoints[WayPointIndex].transform.position; //The position of where the enemy needs to go
TargetedPosition.z = 0f;
var MoveThisFrame = EnemyMovingSpeed * Time.deltaTime;
transform.position = Vector2.MoveTowards(this.transform.position, TargetedPosition, MoveThisFrame);
if(transform.position == TargetedPosition)
{
WayPointIndex++;
}
}
else
{
Destroy(gameObject);
}
}
// Use this for initialization
void Start () {
transform.position = WayPoints[WayPointIndex].transform.position;
}
// Update is called once per frame
void Update () {
EnemyMoving();
}
}
Problem
You're checking for collisions on the SPAWNER; when someone hits the Spawner it counts down enemies. But the Spawner doesn't have a collision box in the screenshot so it can never be hit. The Scene changing code can never be called.
So the game, based on the code, looks like this:
Spawn X enemies,
Hit the Spawner X times,
(Removed: Destroy the Spawner,)
Change scene.
I'm guessing this is conceptually incorrect and you actually want to check collisions on the spawned enemies, which will then count up the amount of destroyed enemies, and change the scene when they are all dead.
Solution
Conceptually, what you want is:
Spawn X enemies
Count up variable for every enemy
On Enemy death, count it down
When 0, change scene
So how do we code this?
Well, every enemy needs a reference to the object that holds the count. You can do this in several ways, when I personally do it I usually have just one spawner that is responsible for everyone so I make that one a Singleton, that can be references from anywhere:
EnemySpawner
public class EnemySpawner : MonoBehaviour
{
public static Spawner Instance = null;
int CurrentNumOfEnemies = 0;
// ... etc
void Start()
{
if (Instance == null)
Instance = this;
// Spawn enemies like you do already, CurrentNumOfEnemies++ for every spawned
}
public OnEnemyDeath() {
CurrentNumOfEnemies--;
if (CurrentNumOfEnemies < 1)
{
// You killed everyone, change scene:
LevelManager.LoadLevel("Your Level");
}
}
}
Enemy script (I don't know how your current code looks, but here's a minimal solution based on how I THINK your code looks):
void OnDestroy()
{
// This will run automatically when you run Destroy() on this gameObject
EnemySpawner.Instance.OnEnemyDeath(); // Tell the EnemySpawner that someone died
}
This will only work if you have exactly only ONE spawner. If you have multiple ones you will have to send a reference to the instance of its spawner to every spawned enemy. I can show you how to do ths too, if you wish.
Bonus content
LevelManager doesn't need to be on a GameObject, it can be static instead:
Remove the LevelManager script from any GameObject
Change your LevelManager code to this:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public static class LevelManager
{
public static void LoadLevel(string name)
{
Debug.Log("Level loading requested for" + name);
SceneManager.LoadScene(name);
}
}
Now you can use it from ANYWHERE, without needing to initialize a reference to any script or GameObject:
LevelManager.LoadLevel("My Level");
myLevelManager.LoadLevel("NextLevelMenu"); is never executed, because you destroy the object in the if-test above.

Making a sliding door that is unlocked with a key in unity

I've been trying to make a sliding door for my unity level and I've managed to set up the animations but the scripting that's supposed to link up the functions with the objects isn't working.
Here's the script for the key card:
using UnityEngine;
using System.Collections;
public class Key_Pickup_1 : MonoBehaviour {
public GameObject player;
private Player_inventory playerinventory;
void Awake ()
{
playerinventory = player.GetComponent<Player_inventory>();
}
// Update is called once per frame
void onTriggerEnter()
{
if (gameObject == player)
{
playerinventory.hasKey_1 = true;
Destroy(gameObject);
}
}
}
Here's the script for the Door animation:
using UnityEngine;
using System.Collections;
public class Door_Animation_1 : MonoBehaviour {
public string Open;
private Animator anim_1;
public GameObject player;
private Player_inventory playerInventory;
void Start()
{
anim_1 = GetComponent<Animator>();
player = GameObject.FindGameObjectWithTag("Player");
playerInventory = player.GetComponent<Player_inventory>();
}
void OntriggerEnter (Collider other)
{
if(other.gameObject == player)
{
if (playerInventory.hasKey_1)
{
anim_1.SetTrigger(Open);
}
}
}
Any Ideas?
You don't have the proper capitalization for the OnTriggerEnter methods in your code. You have two different spellings and they are both wrong. It must be exactly OnTriggerEnter (or OnTriggerEnter2D for objects with a Collider2D instead of a Collider).

Categories

Resources