Unity3d: server delay in spawning networked RigidBody projectiles - c#

I'm following the official multiplayer networking tutorial, but I'm having some trouble with the "bullets".
Each bullet prefab is spawned on the server-side through a command, according to the position of a spawn point on the player prefab. The basic system works well, but for all players except the host there is a large amount of lag between the location of the spawn point and the spawned bullet.
The bullets are spawned correctly according to the player's location on the server, as expected. However, this is behind the player's client position.
Is there a solution to this? Should I be using RigidBody at all? I've seen methods which use raycasting for projectiles which may be an improvement, but I would like to be able to see the projectiles travel through the air. Any help would be very appreciated!
For reference, the relevant PlayerController code:
using UnityEngine;
using UnityEngine.Networking;
using System.Collections;
public class PlayerController : NetworkBehaviour {
public float speed;
public float turnSpeed;
public GameObject bulletPrefab;
public Transform bulletSpawn;
void Update () {
if (!isLocalPlayer) {
return;
}
float power = Input.GetAxis ("Vertical") * Time.deltaTime * speed;
float turn = Input.GetAxis ("Horizontal") * Time.deltaTime * turnSpeed;
transform.Rotate(0, turn, 0);
transform.Translate (power, 0, 0);
if (Input.GetKeyDown (KeyCode.Space)) {
CmdFire ();
}
}
[Command]
void CmdFire() {
var bullet = (GameObject)Instantiate (bulletPrefab, bulletSpawn.position, bulletSpawn.rotation);
bullet.GetComponent<Rigidbody>().velocity = bullet.transform.forward * 6;
NetworkServer.Spawn (bullet);
Destroy (bullet, 2.0f);
}
}

Related

Player moves at a very slow speed in Unity

I'm making a first-person movement script for the player, and everything movement-wise seems to work fine (other than an unrelated issue of the player not moving in the camera's direction), however when running in the game, the player moves at a very slow speed.
Here's the movement script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
private Rigidbody RB;
[SerializeField] private GameObject cam;
private float walkVel; // Forward & backward movement
private float strafeVel; // Sideways movement
[SerializeField] public float walkSpeed = 5f;
private void Start()
{
RB = GetComponent<Rigidbody>();
}
private void Update()
{
walkVel = Input.GetAxis("Vertical");
strafeVel = Input.GetAxis("Horizontal");
}
private void FixedUpdate()
{
transform.localRotation = Quaternion.Euler(0f, cam.transform.rotation.y * Time.deltaTime, 0f);
Vector3 Up = new Vector3(RB.velocity.x, RB.velocity.y, RB.velocity.z);
RB.velocity = (transform.forward * strafeVel + transform.right * walkVel).normalized * walkSpeed * Time.deltaTime;
}
}
I'm pretty sure the issue is not related to the camera script, but here it is:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerCamPositioning : MonoBehaviour
{
private Vector2 camTurn;
[SerializeField] public float camSensitivity = 5f;
private void Start()
{
Cursor.lockState = CursorLockMode.Locked;
}
private void Update()
{
camTurn.x += Input.GetAxis("Mouse X") * camSensitivity;
camTurn.y -= Input.GetAxis("Mouse Y") * camSensitivity;
transform.localRotation = Quaternion.Euler(camTurn.y, camTurn.x, 0);
}
}
I tried to implement a very basic velocity script, and alternatively RB.AddVelocity to the Rigidbody, however it did not solve my problem.
I also tried simply increasing the walkSpeed variable to increase player speed, which actually solves my problem, HOWEVER I want to refrain from using this solution as previously the player moved at a relatively normal speed with walkSpeed set to 5f.
Sounds like you just need to tweak your values. Try splitting your equation into pieces and logging the individual and multiplied value so you can understand what values you see versus what values you're expecting.
I see many variables in your code that can be less than 1. strafeVel, walkVel and Time.deltaTime. In fact, in my experience, Time.deltaTime is always a very small float.
Perhaps you would prefer to use RB.velocity with += or *= along with a Mathf.Clamp() to gradually increase your speed.
All I had to do to solve my problem was remove Time.deltaTime from the RB.Velocity vector. The vector already runs in the FixedUpdate function, so I think it should work as intended now.

Why does my enemy keep teleporting to the origin in unity?

I just started making a game. For whatever reason, the enemy continuously teleports to the origin for no reason. Here is my code so far;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Enemy : MonoBehaviour
{
public float speed = 0.5f;
public Transform target;
void Start()
{
}
// Update is called once per frame
void Update()
{
transform.LookAt(target);
transform.position = transform.forward * speed * Time.deltaTime;
}
}
I have the target object assigned to the player. Someone please help because I can't find a solution anywhere.
This is because transform.forward is a result axis, not a specific location, and gives you numbers around -1 to 1. To fix that just try:
transform.position += transform.forward * speed * Time.deltaTime;

How can I change this code to find the transform of objects with a specific tag instead of a specific object?

This code tries to find the player and have the zombies play an animation as they do it. My problem is that it isn't following the player however I know why. The reason this happens is because it isn't selecting the player, it selects the prefab of the player in the assets instead of the one in the hierarchy and it makes them buggy. This happens because I have a spawn manager that spawns in the player instead of just placing it in the scene because I want to make the player have a random spawn. I also want a random spawn for the zombies so I can't just add them in the unity editor. I think I can fix this problem if I can make the zombies track the players tag instead of the gameobject. Is there a way to change the code to make it track the players tag? Also if it is not possible please tell me because I don't want to waste time on finding a solution that is not possible. Thanks
Sorry if the code is bad I am a noob.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ZK_Attacking : MonoBehaviour
{
public Transform Player;
public float MoveSpeed = 3.5f;
public float AttackRange = 1.0f;
private Animator anim;
private void Start()
{
anim = GetComponent<Animator>();
Player = GameObject.Find("Player").transform;
}
void Update()
{
transform.LookAt(Player);
float dstSqr = (Player.position - transform.position).sqrMagnitude;
bool inAttackRange = (dstSqr <= AttackRange * AttackRange);
anim.SetBool("AttackingPlayer", inAttackRange);
transform.position += transform.forward * MoveSpeed * Time.deltaTime;
transform.position = Vector3.MoveTowards(transform.position, Player.position, MoveSpeed * Time.deltaTime);
}
}

Moving child GameObject inside moving parent GameObject

I am trying to make a 2.5D SHMUP type game in which the world continuously moves forward while the player's spaceship and camera stay in place. This means that even if the world is moving, if the player's ship is in the middle of the screen it will stay there.
To do this I've created an empty game object named Moving World and attached the following script to it:
public class movingWorldController : MonoBehaviour
{
private float movementSpeed = 5f;
void Update()
{
transform.position = transform.position + new Vector3(0, 0, movementSpeed * Time.deltaTime);
}
}
I then added the camera and spaceship as children to of this object, and as a result they indeed move with the moving world object. However, I also have a script attached to the spaceship to allows it to move according to the player's input, and if I enable the script above the ship stops responding to the player's input. The ship's script looks like this:
public class ShipController : MonoBehaviour
{
public Rigidbody rb;
public float moveSpeed = 5f;
private Vector3 movement;
void Update()
{
movement.x = Input.GetAxisRaw("Horizontal");
movement.z = Input.GetAxisRaw("Vertical");
}
private void FixedUpdate()
{
rb.MovePosition(rb.position + movement * moveSpeed * Time.deltaTime);
}
}
The ship controller works just fine when the world-moving script is disabled, so I suspect the world script is somehow overwriting the spaceship position. How may I solve this?
For a POC example see this video: https://www.youtube.com/watch?v=-fVjWgfUKn4&t=282s (jump to 4:00 to see the game in action). Note that in the video gamemaker is used to achieve the effect, while I am trying to achieve a similar effect using just code.
I achieved the effect I was aiming for by doing the following. First, I removed the MovingWorld object and instead applied the following script to the camera:
public class movingWorldController : MonoBehaviour
{
public float movementSpeed = 5f;
void FixedUpdate()
{
transform.position = transform.position + new Vector3(0, 0, movementSpeed * Time.deltaTime);
}
}
This will cause the camera to continuously move forward. Next, to make sure the player's ship keeps up with the camera, and is maneuverable at the same time, I applied the following script to the ship's object:
public class ShipController : MonoBehaviour
{
public Rigidbody rb;
private float shipVelocity = 5f;
public float moveSpeed = 10f;
private Vector3 movement;
void Update()
{
movement.x = Input.GetAxisRaw("Horizontal") * moveSpeed;
movement.z = Input.GetAxisRaw("Vertical") * moveSpeed + shipVelocity;
}
private void FixedUpdate()
{
rb.MovePosition(rb.position + movement * Time.deltaTime);
}
}
Two important notes:
The shipVelocity variable was introduced to make sure the ship continues to cruise at camera-speed.
Even though the camera is not a RigidBody its position update must occur during the FixedUpdate method to make sure it moves on the same frame as the ship. Updating it using the Update method will introduce jittering to the ship due to de-synchronization.

Unity3D C#. Using the transform.RotateAround() function while keep the distance between two objects constant

I am trying to practice making third person controllers in Unity 3D. I am a beginner, and I am completely baffled on how to make my controller functional. I have been doing hours of research, but no thread I can find seem to answer my question. I have two scripts, a CameraController, and a CharacterController. My code is below.
CameraController:
using UnityEngine;
using System.Collections;
public class CameraController : MonoBehaviour {
public GameObject target;
public float rotationSpeed;
Vector3 offset;
Vector3 CameraDestination;
// Use this for initialization
void Start () {
offset = transform.position - target.transform.position;
CameraDestination = offset + transform.position;
rotationSpeed = 50f;
transform.position = CameraDestination;
}
// Update is called once per frame
void Update () {
transform.LookAt (target.transform.position);
float h = Input.GetAxisRaw ("Horizontal");
transform.RotateAround (target.transform.position, Vector3.up, Time.deltaTime * h * rotationSpeed);
target.transform.Rotate (0f, Time.deltaTime * h * rotationSpeed, 0f);
}
}
CharacterController:
using UnityEngine;
using System.Collections;
public class CharController : MonoBehaviour {
public float playerSpeed = 10f;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
float Vertical = Input.GetAxis("Vertical");
transform.position += transform.forward * Time.deltaTime * playerSpeed * Vertical;
}
}
When either the left or right arrow key is pressed, both the player and the camera rotates. If I try to attach the camera to the player as a children, the camera's rotation becomes messed up, but if I do not attach the camera to the player, the camera stops following the player. If I try to set the camera to a specific position relative to the player, it stops revolving around the player like it is intended to do. I simply can not come up with a method that works.Thank you for answering my question in advance!
When I go about this, I like to have an empty gameObject which has 2 children, the camera and then the mesh of the character.
> CharacterController
> Camera
> CharacterRig
When you want to rotate the character, rotate the CharacterController, then when you want to rotate the Camera around the character, change your code to:
transform.RotateAround (CharacterRig.transform.position, Vector3.up, Time.deltaTime * h * rotationSpeed);
This will allow your camera to rotate irrespective of any character animation and should solve your issue. This is very important if you want to implement animations later, as you don't want to parent the camera to the thing that is being animated because it will move with the animation.
P.s. Your code appears fine. Certain that it is purely the way you have set up the game objects.

Categories

Resources