Transmiting a parameter in multiplayer - unity3d

I am working on a Unity 2D fps multiplayer game. Whenever a player presses Space they instantiate a bullet and when a bullet hits any player it has to destroy itself and push the player in the bullet direction. My code looks like this:
void OnTriggerEnter2D(Collider2D col)
{
if (isServer == false)
return;
if (col.gameObject.tag != "bullet")
return;
CmdTrigger(col.gameObject);
}
[Command]
void CmdTrigger(GameObject col)
{
RpcTrigger(col);
}
[ClientRpc]
void RpcTrigger(GameObject col)
{
Rigidbody2D rb;
rb = col.GetComponent<Rigidbody2D>();
if (rb.velocity.x > 0)
RpcExplode(Mathf.Sign(1));
else
RpcExplode(Mathf.Sign(-1));
//Network.Destroy(col);
}
The problem is that when a bullet collides a player I can't transmit well the GameObject to the other players so every player can destroy the bullet on their client. When a bullet hits a player it doesn't destroy itself, it just passes through and the Console shows me this error: "NullRefrenceException: Object reference not set to an instance of an object", and if I click on it, it brings me to this line:
rb = col.GetComponent<Rigidbody2D>();
Here is my character control full code: https://pastebin.com/L1DEmQv1
Any ideas? It is very important for me to fix it as soon as possible. Thanks.

Related

Weapon Pick-Up and shoot

I'm new to Unity and I was wondering if anyone knows how to make the player pick up a weapon and shoot it in Unity 2D. I have already made the sprite for the gun and I've been trying to pick it up with this code:
public GameObject player;
void Update() {
void OnTriggerEnter2D(Collider2D col) {
if (col.tag == "Player") {
gameObject.transform.position = new Vector3(player.transform.position.x + 2, player.transform.position.y, player.transform.position.z);
}
}
}
The gun is set as a trigger and has no rigidbody. All the youtube tutorials show how to pick up an object and then destroys it, but don't show how to "hold" the object.
If you do player.transform.position.x + 2, that sets the gun to the x position of the player + 2. This is not a good way of doing it.
My advice is to do it this way instead.
Copy the gun.
Parent the copy to the camera
Place the gun somewhere on your player.
Disable the gun
In your player script add this line
public GameObject weapon;
Now, in your weapon pickup script, change the player reference to whatever your player script is called instead of a GameObject.
For example, lets assume your player script is called PlayerScript.cs, instead of
public GameObject player;
You should do
public PlayerScript player;
Now, we have a reference to the player script. We can now access the weapon.
Change the OnTrigger to the following:
void OnTriggerEnter2D(Collider2D col) {
if (col.tag == "Player") {
// Set the weapon active
player.weapon.SetActive(true);
// Destroy this pick-up
Destroy(gameObject);
}
}
Also, in your code you have ontriggerenter inside the update method. That is not how it works. Make sure the method is outside of the update method.
Now when you touch the gun on the floor. It should now enable the gun in the players hand and destroy the one on the floor.
In the editor, drag the players gun to the weapon field in the player script.
Also, drag the player to the player field of the gun on the ground.
Hope this helps, feel free to ask more questions if this doesn't work. Keep us updated. :)

Movement stops whenever player touches ground

I am trying to learn the basics of unity collision and I want the movement of the player to stop whenever it touches an obstacle but the movement stops whenever it touches the ground. I tagged the obstacle with a tag called obstacle and left the ground untagged but whenever the player touches the ground it stops all movement. Does anyone know how to fix this? Heres my code: `using UnityEngine;
public class PlayerCollision : MonoBehaviour
{
public Movement playerMovement;
void OnCollisionEnter(Collision collisionInfo)
{
Debug.Log(collisionInfo.collider.tag == "Obstacle");{
playerMovement.enabled = false;
}
}
}
The code you've written stops the movement of the player whenever its collides with something. The code wouldn't even compile because of the "{" at the end.
void OnCollisionEnter(Collision collisionInfo)
{
// returns true or false in the console depending on whether player its colliding with the obstacle
// code won't compile because of the "{" at the end
Debug.Log(collisionInfo.collider.tag == "Obstacle");{
playerMovement.enabled = false;
}
To fix that you can use an if statement and remove the "{" at the end like shown below.
It is also recommended to use CompareTag when working with tags.
void OnCollisionEnter(Collision collisionInfo)
{
if(collisionInfo.collider.CompareTag("Obstacle"))
{
playerMovement.enabled = false;
}
}

Unity2D: play instantiated prefab's animation when prefab is being dragged

I have a prefab that is instantiated when the user buys the item from my In-game store, how ever many is instantiated, the all of prefab has a start position of a certain position. The prefab can be dragged around the scene using this TouchScript package I found online! My issue: I want to play the prefab's animation every time the user is dragging the prefab around the screen, I attempted this by creating a RaycastHit2D function that would allow me to detect if the user has clicked on the prefab's collider, script below:
if (Input.GetMouseButtonDown (0)) {
Vector2 worldPoint = Camera.main.ScreenToWorldPoint (Input.mousePosition);
RaycastHit2D hit = Physics2D.Raycast (worldPoint, Vector2.zero);
if (hit.collider != null) {
if (this.gameObject.name == "Item5 (1)(Clone)" +item5Increase.i) {
monkeyAnim.SetBool ("draging", true);
Debug.Log (hit.collider.name);
}
} else {
monkeyAnim.SetBool ("draging", false);
}
}
However if I were to buy more than one prefab, all instantiated prefabs will play it's animation when I start to drag only one of the instantiated prefabs, hope I'm making sense. Can some one help me? Thank you!
I faced a similar issue with platforms in my 2D game. The solution I would suggest is to create a GameObject that acts as the current item you wish to animate, and a LayerMask that acts as a filter for which objects your raycast can hit. You can use this LayerMask in conjunction with the Physics2D.Raycast API, which has an overload method that takes a LayerMask as a parameter.
Start by creating a new layer, which can be done by going to the top right of an object in your scene and accessing the "Layer" box. Once you've created a new layer (I called mine "item"), make sure your prefab's layer is assigned correctly.
Then, create an empty object in your scene, and attach this script to it. On that object you will see a dropdown menu that asks which layers your raycast should hit. Assign it the "item" layer; this ensures that your raycast can only hit objects in that layer, so clicking on anything else in your game will produce no effect.
using UnityEngine;
public class ItemAnimation : MonoBehaviour
{
private GameObject itemToAnimate;
private Animator itemAnim;
[SerializeField]
private LayerMask itemMask;
private void Update()
{
if (Input.GetMouseButtonDown(0))
{
CheckItemAnimations();
}
else if (Input.GetMouseButtonUp(0) && itemToAnimate != null) //reset the GameObject once the user is no longer holding down the mouse
{
itemAnim.SetBool("draging", false);
itemToAnimate = null;
}
}
private void CheckItemAnimations()
{
Vector2 worldPoint = Camera.main.ScreenToWorldPoint(Input.mousePosition);
RaycastHit2D hit = Physics2D.Raycast(worldPoint, Vector2.zero, 1, itemMask);
if (hit) //if the raycast hit an object in the "item" layer
{
itemToAnimate = hit.collider.gameObject;
itemAnim = itemToAnimate.GetComponent<Animator>();
itemAnim.SetBool("draging", true);
Debug.Log(itemToAnimate.name);
}
else //the raycast didn't make contact with an item
{
return;
}
}
}

Mouse Click inside OnTriggerEnter

Video URL for easy understanding - http://tinypic.com/r/28jdyyq/9
In this video, you can see my problem, when the sword touches the enemy.. enemy gets destroyed.. But i want when i mouseclick (or hit), then only ..enemy should destroy..
void OnTriggerEnter(Collider col)
{
if (col.GetComponent<Collider>().tag == "enemy")
{
Destroy(col.gameObject);
}
}
This is my code, i have enemy and Player with sword (with collider) , everything is perfect, i want when i click mousebutton then only sword should kill enemy,
But, What is happening when i bring my player (with sword) near enemy and sword touches enemy, it is killing enemy without i hit by sword.
I tried the below code also by adding mouse click event inside Trigger , but nothing happens. Any idea Please
void OnTriggerEnter(Collider col)
{
if (Input.GetButtonDown("Fire1")){
if (col.GetComponent<Collider>().tag == "enemy"){
Destroy(col.gameObject);
}
}
}
Here is code for Swing -
if (Input.GetButtonDown("Fire1"))
{
anim.SetTrigger("hit");
}
Here hit is trigger in animation controller and make transition to the animation clip
you can use Animation Events to make true a Boolean when the sword rises in animation and turn it to false when the sword goes down and check that Boolean when OnTriggerEnter is called
make a variable like hit set it to true and false via animation Event
public bool hit;
void OnTriggerEnter(Collider col)
{
if (hit){
if (col.GetComponent<Collider>().tag == "enemy"){
Destroy(col.gameObject);
}
}

In Unity how to "throw" a sprite with a player if both has rigidbody2d and colliders?

I've got a player and I would like to throw an item what is "attached" to the player.
The problem is that both has rigidbody2D and Collider components. The item what I would like to throw is with the player and it has to collide with the ground and stuff. (except the player)
Here is what I tried:
if (Input.GetButtonDown ("Fire1") && canThrowCandle) {
Candle.rigidbody2D.isKinematic = false;
if (faceingRight)
Candle.rigidbody2D.AddForce(new Vector2(400f, 400f));
else if (!faceingRight)
Candle.rigidbody2D.AddForce(new Vector2(-400f, 400f));
Candle.collider2D.enabled = true;
canThrowCandle = false;
}
And then if the player collides with the item (Candle), it is with the player again:
void OnCollisionEnter2D(Collision2D coll){
if (coll.gameObject.name == "Candle") {
canThrowCandle = true;
Candle.rigidbody2D.isKinematic = true;
Candle.collider2D.enabled = false;
}
And the the code (CandleController) what controls the position of the ithem that I would like to throw:
void Update () {
if (GameObject.Find ("Player").GetComponent<PlayerController> ().canThrowCandle)
transform.position = new Vector3 (player.transform.position.x, player.transform.position.y, -0.01f);
}
So the question is, that how can I make this work?
If I understand correctly that you want the candle to go inside the player but both of them need to collide with the ground.
This can be done using collision layers. Just put ground, player and candle to different layers. Then adjust that both player and candle are colliding with ground, but not with each other.
If you want both trigger collider and physics collider to be attached to same gameObject, I think you need to use child gameObject for that as mentioned here.