- Home /
Unet igonore collisions between layers?
So this is about the 5th time I asked this question, just hoping that someone can help me out through this frustrating process. I want to ignore the collisions between my "spell" layer game objects, and my "LocalPlayer" capsule collider, so the player's own spells do not damage the player. I believe I setup the layers correctly in my PlayerController script, but I have tried so many things to try to ignore these layer collisions. I went to the physics chart and unchecked the collision box between the two layers as well as adding phyics.ignorelayermaskcollision which only worked on the lan host side, while the client could still shoot itself and not shoot the lan host. My hit detection script is assigned to a game object that is spawned on the server. Any help is appreciated thanks!
//Player Controller using System.Collections; using System.Collections.Generic; using UnityEngine.Networking; using UnityEngine.UI; using UnityEngine; [RequireComponent(typeof(PlayerMotor))] public class PlayerController : NetworkBehaviour {
public AudioListener listener;
[SerializeField]
[SyncVar]
public float speed = 5f;
[SerializeField]
private float lookSensitivity = 3f;
[SerializeField]
Behaviour[] disableComponents;
[SerializeField]
private PlayerMotor motor;
private Health health;
public Camera cam;
public Image healthBar;
void Start () {
if (!isLocalPlayer) {
AssignRemoteLayer ();
ComponentsToDisable ();
}
RegisterPlayer ();
}
void Update () {
if (!isLocalPlayer) {
return;
}
MovePlayer ();
playerUI ();
}
void ComponentsToDisable() {
for (int i = 0; i < disableComponents.Length; i++) {
disableComponents [i].enabled = false;
}
}
void AssignRemoteLayer () {
gameObject.layer = LayerMask.NameToLayer ("RemotePlayer");
foreach (Transform t in transform) {
t.gameObject.layer = LayerMask.NameToLayer ("RemotePlayer");
}
}
void RegisterPlayer () {
motor = GetComponent<PlayerMotor> ();
string ID = "Player " + GetComponent<NetworkIdentity> ().netId;
transform.name = ID;
}
void MovePlayer () {
//all of this is for moving the character
float xMove = Input.GetAxis ("Horizontal");
float zMove = Input.GetAxis ("Vertical");
float yMove = Input.GetAxis ("Jump");
Vector3 moveHorizontal = transform.right * xMove;
Vector3 moveVertical = transform.forward * zMove;
Vector3 jump = transform.up * yMove;
Vector3 velocity = (moveHorizontal + moveVertical + jump).normalized * speed;
//used to move the character
motor.Move (velocity);
//this is for only turning the character
float yRot = Input.GetAxisRaw ("Mouse X");
Vector3 rotation = new Vector3 (0f, yRot, 0f) * lookSensitivity;
motor.Rotate (rotation);
float xRot = Input.GetAxisRaw ("Mouse Y");
float cameraRotation = xRot * lookSensitivity;
motor.RotateCamera (cameraRotation);
}
void playerUI() {
health = GetComponent<Health> ();
healthBar.fillAmount = (health.currentHealth/100f);
}
public void temporarySlow () {
StartCoroutine (slowMovement ());
}
IEnumerator slowMovement () {
speed = 0f;
yield return new WaitForSeconds (3f);
speed = 5f;
}
}
//hit detection
using System.Collections; using System.Collections.Generic; using UnityEngine.Networking; using UnityEngine;
public class hitDetection : NetworkBehaviour {
public int damage;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
}
void OnTriggerEnter (Collider col) {
var hit = col.gameObject;
var health = hit.GetComponent<Health> ();
if (health != null) {
health.TakeDamage (damage);
}
}
}
Answer by DominikHeyn · Feb 23, 2017 at 06:10 PM
Hey there,
I'll tell you how I managed to, kind of, understand UNET. Everytime a local player (client) wants to do something, it should notice the server about it. You do this by using so called Commands. A command is the way a client says:
"Hey Server! I'd like you to inform you that I want to change a layer!"
In your case I suggest to make "AssignToLayer" a command. You'll do this as followed:
[Command] private void CmdAssignToLayer(string layerName) {
gameObject.layer = LayerMask.NameToLayer(layerName);
}
Note that I put a "Cmd" as a prefix in front of your method's name. Additionally, I'd suggest you pass the layer name or the int value of that layer in the Command. At this point the server knows that you want to change a layer.
I hope this solves your problem.
Dominik
So I updated the script and I think what is happening is whoever is lan host is considered the local player, but when I add a client, on the separate window I do not think he is considered the local player for himself, but is the remote player on both ends. The lan host seems to be the local player for the client end as well because the client cannot shoot the host but can shoot himself, even though the local player on the lan host screen cannot shoot himself.
using System.Collections;
using System.Collections.Generic;
using UnityEngine.Networking;
using UnityEngine.UI;
using UnityEngine;
[RequireComponent(typeof(Player$$anonymous$$otor))]
public class PlayerController : NetworkBehaviour {
public AudioListener listener;
[SerializeField]
[SyncVar]
public float speed = 5f;
[SerializeField]
private float lookSensitivity = 3f;
[SerializeField]
Behaviour[] disableComponents;
[SerializeField]
private Player$$anonymous$$otor motor;
private Health health;
private string remoteLayer;
private string localLayer;
public Camera cam;
public Image healthBar;
void Start () {
if (!isLocalPlayer) {
remoteLayer = "RemotePlayer";
CmdAssignRemoteLayer (remoteLayer);
ComponentsToDisable ();
}
if (isLocalPlayer == true) {
localLayer = "LocalPlayer";
CmdAssignLocalPlayer(localLayer);
}
RegisterPlayer ();
}
void Update () {
if (!isLocalPlayer) {
return;
}
$$anonymous$$ovePlayer ();
playerUI ();
}
void ComponentsToDisable() {
for (int i = 0; i < disableComponents.Length; i++) {
disableComponents [i].enabled = false;
}
}
[Command]
private void CmdAssignRemoteLayer (string remoteLayer) {
gameObject.layer = Layer$$anonymous$$ask.NameToLayer (remoteLayer);
foreach (Transform t in transform) {
t.gameObject.layer = Layer$$anonymous$$ask.NameToLayer (remoteLayer);
}
}
[Command]
private void CmdAssignLocalPlayer(string localLayer) {
gameObject.layer = Layer$$anonymous$$ask.NameToLayer ("LocalPlayer");
foreach (Transform t in transform) {
t.gameObject.layer = Layer$$anonymous$$ask.NameToLayer ("LocalPlayer");
}
}
void RegisterPlayer () {
motor = GetComponent<Player$$anonymous$$otor> ();
string ID = "Player " + GetComponent<NetworkIdentity> ().netId;
transform.name = ID;
}
Your answer
Follow this Question
Related Questions
Unity networking tutorial? 6 Answers
Reducing server-side application size 0 Answers
OnServerStart not working in Build. Works in editor 1 Answer
RPC ordering details 0 Answers
Why doesn't an object appear on both screens? (Unity networking) 2 Answers