I am trying to build a VR app for Oculus go. I am trying to move OVRPlayerContoller by pointing at a position on the ground, clicking to set a target position and then your character moves towards it. The player controller does not move towards the pointed position even tho the object is created on that position.I have written this script for it and attached and attached it to OVRPlayerController.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ClickToMove : MonoBehaviour
{
private Vector3 targetPos; //This Vector3 will store the position where we click to move.
private bool Moving = false; //This bool keeps track of whether we are in the process of moving or not.
private GameObject targetInstance;
//The variables we want to customize. Added info headers to these for the Unity Editor.
[Header("Our Go controller object")]
public GameObject goController;
[Header("Movement Speed")]
public float speed = 1;
[Header("Stop When This Far Away From Target")]
public float haltDistance = 0;
[Header("Optional Target Object")]
public GameObject targetObj;
void Update()
{
MoveToTarget(); //Here we simply run our MoveToTarget method in the Update method.
//That way we don't clutter up the Update method with too much code.
}
void MoveToTarget() //Here we do the cluttering instead.
{
var ray = new Ray(goController.transform.position, goController.transform.forward); //Create a ray going from the goController position and in the Forward direction of the goController.
RaycastHit hitInfo; //Store info about what the ray hits.
Physics.Raycast(ray, out hitInfo, 100);
if (OVRInput.GetUp(OVRInput.Button.PrimaryIndexTrigger)) //If we release the trigger..
{
targetPos = hitInfo.point; //Make our targetPos assume the positional value of the hit point.
if (targetObj) //If we have specified a Target Object to mark where we click.
//If we didn't, then we don't want to try to instantiate it.
{
if (targetInstance) //If there is already a Target Object in the scene.
{
Destroy(targetInstance); //Destroy it.
}
targetInstance = Instantiate(targetObj, targetPos, transform.rotation); //Create our Target object at the position we clicked.
}
Moving = true; //And finally we set Moving to True.
}
if (Moving == true) //Since Moving is now true
{
transform.position = Vector3.MoveTowards(transform.position, new Vector3(targetPos.x, transform.position.y, targetPos.z), speed * Time.deltaTime); //Transform our x and z position to move towards the targetPos.
//Note that our y position is kept at default transform position since we only want to move along the ground plane.
}
if (Vector3.Distance(transform.position, targetPos) <= haltDistance + 1) //Check proximity to targetPos. Mainly useful to keep your player from setting a target position right next to say a building and then end up clipping through half of it.
{
if (targetInstance) //If we created a Target Object..
{
Destroy(targetInstance); //Then we want to destroy it when we reach it.
}
Moving = false; //Since we have now arrived at our target destination.
}
}
}
I created a cube prefab for the Target Object and Dragged the TrackedRemote Prefab(which contains Go controller model and script) onto the Go Contoller slot.
Then I created a ray from my controller using the script below and attached it to OVRCameraRig.
using UnityEngine;
using UnityEngine.Events;
public class VRRaycaster : MonoBehaviour
{
[System.Serializable]
public class Callback : UnityEvent<Ray, RaycastHit> { }
public Transform leftHandAnchor = null;
public Transform rightHandAnchor = null;
public Transform centerEyeAnchor = null;
public LineRenderer lineRenderer = null;
public float maxRayDistance = 500.0f;
public LayerMask excludeLayers;
public VRRaycaster.Callback raycastHitCallback;
void Awake()
{
if (leftHandAnchor == null)
{
Debug.LogWarning("Assign LeftHandAnchor in the inspector!");
GameObject left = GameObject.Find("LeftHandAnchor");
if (left != null)
{
leftHandAnchor = left.transform;
}
}
if (rightHandAnchor == null)
{
Debug.LogWarning("Assign RightHandAnchor in the inspector!");
GameObject right = GameObject.Find("RightHandAnchor");
if (right != null)
{
rightHandAnchor = right.transform;
}
}
if (centerEyeAnchor == null)
{
Debug.LogWarning("Assign CenterEyeAnchor in the inspector!");
GameObject center = GameObject.Find("CenterEyeAnchor");
if (center != null)
{
centerEyeAnchor = center.transform;
}
}
if (lineRenderer == null)
{
Debug.LogWarning("Assign a line renderer in the inspector!");
lineRenderer = gameObject.AddComponent<LineRenderer>();
lineRenderer.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off;
lineRenderer.receiveShadows = false;
lineRenderer.widthMultiplier = 0.02f;
}
}
Transform Pointer
{
get
{
OVRInput.Controller controller = OVRInput.GetConnectedControllers();
if ((controller & OVRInput.Controller.LTrackedRemote) != OVRInput.Controller.None)
{
return leftHandAnchor;
}
else if ((controller & OVRInput.Controller.RTrackedRemote) != OVRInput.Controller.None)
{
return rightHandAnchor;
}
// If no controllers are connected, we use ray from the view camera.
// This looks super ackward! Should probably fall back to a simple reticle!
return centerEyeAnchor;
}
}
void Update()
{
Transform pointer = Pointer;
if (pointer == null)
{
return;
}
Ray laserPointer = new Ray(pointer.position, pointer.forward);
if (lineRenderer != null)
{
lineRenderer.SetPosition(0, laserPointer.origin);
lineRenderer.SetPosition(1, laserPointer.origin + laserPointer.direction * maxRayDistance);
}
RaycastHit hit;
if (Physics.Raycast(laserPointer, out hit, maxRayDistance, ~excludeLayers))
{
if (lineRenderer != null)
{
lineRenderer.SetPosition(1, hit.point);
}
if (raycastHitCallback != null)
{
raycastHitCallback.Invoke(laserPointer, hit);
}
}
}
}
The problem is that when I press the trigger, the GameObject is created at that point on the floor but the OVRPlayerController does not move towards it.
I have also attached my OVRPlayerController.cs script below:
using System;
using UnityEngine;
/// <summary>
/// Controls the player's movement in virtual reality.
/// </summary>
[RequireComponent(typeof(CharacterController))]
public class OVRPlayerController : MonoBehaviour
{
/// <summary>
/// The rate acceleration during movement.
/// </summary>
public float Acceleration = 0.1f;
/// <summary>
/// The rate of damping on movement.
/// </summary>
public float Damping = 0.3f;
/// <summary>
/// The rate of additional damping when moving sideways or backwards.
/// </summary>
public float BackAndSideDampen = 0.5f;
/// <summary>
/// The force applied to the character when jumping.
/// </summary>
public float JumpForce = 0.3f;
/// <summary>
/// The rate of rotation when using a gamepad.
/// </summary>
public float RotationAmount = 1.5f;
/// <summary>
/// The rate of rotation when using the keyboard.
/// </summary>
public float RotationRatchet = 45.0f;
/// <summary>
/// The player will rotate in fixed steps if Snap Rotation is enabled.
/// </summary>
[Tooltip("The player will rotate in fixed steps if Snap Rotation is enabled.")]
public bool SnapRotation = true;
/// <summary>
/// How many fixed speeds to use with linear movement? 0=linear control
/// </summary>
[Tooltip("How many fixed speeds to use with linear movement? 0=linear control")]
public int FixedSpeedSteps;
/// <summary>
/// If true, reset the initial yaw of the player controller when the Hmd pose is recentered.
/// </summary>
public bool HmdResetsY = true;
/// <summary>
/// If true, tracking data from a child OVRCameraRig will update the direction of movement.
/// </summary>
public bool HmdRotatesY = true;
/// <summary>
/// Modifies the strength of gravity.
/// </summary>
public float GravityModifier = 0.379f;
/// <summary>
/// If true, each OVRPlayerController will use the player's physical height.
/// </summary>
public bool useProfileData = true;
/// <summary>
/// The CameraHeight is the actual height of the HMD and can be used to adjust the height of the character controller, which will affect the
/// ability of the character to move into areas with a low ceiling.
/// </summary>
[NonSerialized]
public float CameraHeight;
/// <summary>
/// This event is raised after the character controller is moved. This is used by the OVRAvatarLocomotion script to keep the avatar transform synchronized
/// with the OVRPlayerController.
/// </summary>
public event Action<Transform> TransformUpdated;
/// <summary>
/// This bool is set to true whenever the player controller has been teleported. It is reset after every frame. Some systems, such as
/// CharacterCameraConstraint, test this boolean in order to disable logic that moves the character controller immediately
/// following the teleport.
/// </summary>
[NonSerialized] // This doesn't need to be visible in the inspector.
public bool Teleported;
/// <summary>
/// This event is raised immediately after the camera transform has been updated, but before movement is updated.
/// </summary>
public event Action CameraUpdated;
/// <summary>
/// This event is raised right before the character controller is actually moved in order to provide other systems the opportunity to
/// move the character controller in response to things other than user input, such as movement of the HMD. See CharacterCameraConstraint.cs
/// for an example of this.
/// </summary>
public event Action PreCharacterMove;
/// <summary>
/// When true, user input will be applied to linear movement. Set this to false whenever the player controller needs to ignore input for
/// linear movement.
/// </summary>
public bool EnableLinearMovement = true;
/// <summary>
/// When true, user input will be applied to rotation. Set this to false whenever the player controller needs to ignore input for rotation.
/// </summary>
public bool EnableRotation = true;
protected CharacterController Controller = null;
protected OVRCameraRig CameraRig = null;
private float MoveScale = 1.0f;
private Vector3 MoveThrottle = Vector3.zero;
private float FallSpeed = 0.0f;
private OVRPose? InitialPose;
public float InitialYRotation { get; private set; }
private float MoveScaleMultiplier = 1.0f;
private float RotationScaleMultiplier = 1.0f;
private bool SkipMouseRotation = true; // It is rare to want to use mouse movement in VR, so ignore the mouse by default.
private bool HaltUpdateMovement = false;
private bool prevHatLeft = false;
private bool prevHatRight = false;
private float SimulationRate = 60f;
private float buttonRotation = 0f;
private bool ReadyToSnapTurn; // Set to true when a snap turn has occurred, code requires one frame of centered thumbstick to enable another snap turn.
void Start()
{
// Add eye-depth as a camera offset from the player controller
var p = CameraRig.transform.localPosition;
p.z = OVRManager.profile.eyeDepth;
CameraRig.transform.localPosition = p;
}
void Awake()
{
Controller = gameObject.GetComponent<CharacterController>();
if (Controller == null)
Debug.LogWarning("OVRPlayerController: No CharacterController attached.");
// We use OVRCameraRig to set rotations to cameras,
// and to be influenced by rotation
OVRCameraRig[] CameraRigs = gameObject.GetComponentsInChildren<OVRCameraRig>();
if (CameraRigs.Length == 0)
Debug.LogWarning("OVRPlayerController: No OVRCameraRig attached.");
else if (CameraRigs.Length > 1)
Debug.LogWarning("OVRPlayerController: More then 1 OVRCameraRig attached.");
else
CameraRig = CameraRigs[0];
InitialYRotation = transform.rotation.eulerAngles.y;
}
void OnEnable()
{
OVRManager.display.RecenteredPose += ResetOrientation;
if (CameraRig != null)
{
CameraRig.UpdatedAnchors += UpdateTransform;
}
}
void OnDisable()
{
OVRManager.display.RecenteredPose -= ResetOrientation;
if (CameraRig != null)
{
CameraRig.UpdatedAnchors -= UpdateTransform;
}
}
void Update()
{
//Use keys to ratchet rotation
if (Input.GetKeyDown(KeyCode.Q))
buttonRotation -= RotationRatchet;
if (Input.GetKeyDown(KeyCode.E))
buttonRotation += RotationRatchet;
}
protected virtual void UpdateController()
{
if (useProfileData)
{
if (InitialPose == null)
{
// Save the initial pose so it can be recovered if useProfileData
// is turned off later.
InitialPose = new OVRPose()
{
position = CameraRig.transform.localPosition,
orientation = CameraRig.transform.localRotation
};
}
var p = CameraRig.transform.localPosition;
if (OVRManager.instance.trackingOriginType == OVRManager.TrackingOrigin.EyeLevel)
{
p.y = OVRManager.profile.eyeHeight - (0.5f * Controller.height) + Controller.center.y;
}
else if (OVRManager.instance.trackingOriginType == OVRManager.TrackingOrigin.FloorLevel)
{
p.y = -(0.5f * Controller.height) + Controller.center.y;
}
CameraRig.transform.localPosition = p;
}
else if (InitialPose != null)
{
// Return to the initial pose if useProfileData was turned off at runtime
CameraRig.transform.localPosition = InitialPose.Value.position;
CameraRig.transform.localRotation = InitialPose.Value.orientation;
InitialPose = null;
}
CameraHeight = CameraRig.centerEyeAnchor.localPosition.y;
if (CameraUpdated != null)
{
CameraUpdated();
}
UpdateMovement();
Vector3 moveDirection = Vector3.zero;
float motorDamp = (1.0f + (Damping * SimulationRate * Time.deltaTime));
MoveThrottle.x /= motorDamp;
MoveThrottle.y = (MoveThrottle.y > 0.0f) ? (MoveThrottle.y / motorDamp) : MoveThrottle.y;
MoveThrottle.z /= motorDamp;
moveDirection += MoveThrottle * SimulationRate * Time.deltaTime;
// Gravity
if (Controller.isGrounded && FallSpeed <= 0)
FallSpeed = ((Physics.gravity.y * (GravityModifier * 0.002f)));
else
FallSpeed += ((Physics.gravity.y * (GravityModifier * 0.002f)) * SimulationRate * Time.deltaTime);
moveDirection.y += FallSpeed * SimulationRate * Time.deltaTime;
if (Controller.isGrounded && MoveThrottle.y <= transform.lossyScale.y * 0.001f)
{
// Offset correction for uneven ground
float bumpUpOffset = Mathf.Max(Controller.stepOffset, new Vector3(moveDirection.x, 0, moveDirection.z).magnitude);
moveDirection -= bumpUpOffset * Vector3.up;
}
if (PreCharacterMove != null)
{
PreCharacterMove();
Teleported = false;
}
Vector3 predictedXZ = Vector3.Scale((Controller.transform.localPosition + moveDirection), new Vector3(1, 0, 1));
// Move contoller
Controller.Move(moveDirection);
Vector3 actualXZ = Vector3.Scale(Controller.transform.localPosition, new Vector3(1, 0, 1));
if (predictedXZ != actualXZ)
MoveThrottle += (actualXZ - predictedXZ) / (SimulationRate * Time.deltaTime);
}
public virtual void UpdateMovement()
{
if (HaltUpdateMovement)
return;
if (EnableLinearMovement)
{
bool moveForward = Input.GetKey(KeyCode.W) || Input.GetKey(KeyCode.UpArrow);
bool moveLeft = Input.GetKey(KeyCode.A) || Input.GetKey(KeyCode.LeftArrow);
bool moveRight = Input.GetKey(KeyCode.D) || Input.GetKey(KeyCode.RightArrow);
bool moveBack = Input.GetKey(KeyCode.S) || Input.GetKey(KeyCode.DownArrow);
bool dpad_move = false;
if (OVRInput.Get(OVRInput.Button.DpadUp))
{
moveForward = true;
dpad_move = true;
}
if (OVRInput.Get(OVRInput.Button.DpadDown))
{
moveBack = true;
dpad_move = true;
}
MoveScale = 1.0f;
if ((moveForward && moveLeft) || (moveForward && moveRight) ||
(moveBack && moveLeft) || (moveBack && moveRight))
MoveScale = 0.70710678f;
// No positional movement if we are in the air
if (!Controller.isGrounded)
MoveScale = 0.0f;
MoveScale *= SimulationRate * Time.deltaTime;
// Compute this for key movement
float moveInfluence = Acceleration * 0.1f * MoveScale * MoveScaleMultiplier;
// Run!
if (dpad_move || Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift))
moveInfluence *= 2.0f;
Quaternion ort = transform.rotation;
Vector3 ortEuler = ort.eulerAngles;
ortEuler.z = ortEuler.x = 0f;
ort = Quaternion.Euler(ortEuler);
if (moveForward)
MoveThrottle += ort * (transform.lossyScale.z * moveInfluence * Vector3.forward);
if (moveBack)
MoveThrottle += ort * (transform.lossyScale.z * moveInfluence * BackAndSideDampen * Vector3.back);
if (moveLeft)
MoveThrottle += ort * (transform.lossyScale.x * moveInfluence * BackAndSideDampen * Vector3.left);
if (moveRight)
MoveThrottle += ort * (transform.lossyScale.x * moveInfluence * BackAndSideDampen * Vector3.right);
moveInfluence = Acceleration * 0.1f * MoveScale * MoveScaleMultiplier;
#if !UNITY_ANDROID // LeftTrigger not avail on Android game pad
moveInfluence *= 1.0f + OVRInput.Get(OVRInput.Axis1D.PrimaryIndexTrigger);
#endif
Vector2 primaryAxis = OVRInput.Get(OVRInput.Axis2D.PrimaryThumbstick);
// If speed quantization is enabled, adjust the input to the number of fixed speed steps.
if (FixedSpeedSteps > 0)
{
primaryAxis.y = Mathf.Round(primaryAxis.y * FixedSpeedSteps) / FixedSpeedSteps;
primaryAxis.x = Mathf.Round(primaryAxis.x * FixedSpeedSteps) / FixedSpeedSteps;
}
if (primaryAxis.y > 0.0f)
MoveThrottle += ort * (primaryAxis.y * transform.lossyScale.z * moveInfluence * Vector3.forward);
if (primaryAxis.y < 0.0f)
MoveThrottle += ort * (Mathf.Abs(primaryAxis.y) * transform.lossyScale.z * moveInfluence *
BackAndSideDampen * Vector3.back);
if (primaryAxis.x < 0.0f)
MoveThrottle += ort * (Mathf.Abs(primaryAxis.x) * transform.lossyScale.x * moveInfluence *
BackAndSideDampen * Vector3.left);
if (primaryAxis.x > 0.0f)
MoveThrottle += ort * (primaryAxis.x * transform.lossyScale.x * moveInfluence * BackAndSideDampen *
Vector3.right);
}
if (EnableRotation)
{
Vector3 euler = transform.rotation.eulerAngles;
float rotateInfluence = SimulationRate * Time.deltaTime * RotationAmount * RotationScaleMultiplier;
bool curHatLeft = OVRInput.Get(OVRInput.Button.PrimaryShoulder);
if (curHatLeft && !prevHatLeft)
euler.y -= RotationRatchet;
prevHatLeft = curHatLeft;
bool curHatRight = OVRInput.Get(OVRInput.Button.SecondaryShoulder);
if (curHatRight && !prevHatRight)
euler.y += RotationRatchet;
prevHatRight = curHatRight;
euler.y += buttonRotation;
buttonRotation = 0f;
#if !UNITY_ANDROID || UNITY_EDITOR
if (!SkipMouseRotation)
euler.y += Input.GetAxis("Mouse X") * rotateInfluence * 3.25f;
#endif
if (SnapRotation)
{
if (OVRInput.Get(OVRInput.Button.SecondaryThumbstickLeft))
{
if (ReadyToSnapTurn)
{
euler.y -= RotationRatchet;
ReadyToSnapTurn = false;
}
}
else if (OVRInput.Get(OVRInput.Button.SecondaryThumbstickRight))
{
if (ReadyToSnapTurn)
{
euler.y += RotationRatchet;
ReadyToSnapTurn = false;
}
}
else
{
ReadyToSnapTurn = true;
}
}
else
{
Vector2 secondaryAxis = OVRInput.Get(OVRInput.Axis2D.SecondaryThumbstick);
euler.y += secondaryAxis.x * rotateInfluence;
}
transform.rotation = Quaternion.Euler(euler);
}
}
/// <summary>
/// Invoked by OVRCameraRig's UpdatedAnchors callback. Allows the Hmd rotation to update the facing direction of the player.
/// </summary>
public void UpdateTransform(OVRCameraRig rig)
{
Transform root = CameraRig.trackingSpace;
Transform centerEye = CameraRig.centerEyeAnchor;
if (HmdRotatesY && !Teleported)
{
Vector3 prevPos = root.position;
Quaternion prevRot = root.rotation;
transform.rotation = Quaternion.Euler(0.0f, centerEye.rotation.eulerAngles.y, 0.0f);
root.position = prevPos;
root.rotation = prevRot;
}
UpdateController();
if (TransformUpdated != null)
{
TransformUpdated(root);
}
}
/// <summary>
/// Jump! Must be enabled manually.
/// </summary>
public bool Jump()
{
if (!Controller.isGrounded)
return false;
MoveThrottle += new Vector3(0, transform.lossyScale.y * JumpForce, 0);
return true;
}
/// <summary>
/// Stop this instance.
/// </summary>
public void Stop()
{
Controller.Move(Vector3.zero);
MoveThrottle = Vector3.zero;
FallSpeed = 0.0f;
}
/// <summary>
/// Gets the move scale multiplier.
/// </summary>
/// <param name="moveScaleMultiplier">Move scale multiplier.</param>
public void GetMoveScaleMultiplier(ref float moveScaleMultiplier)
{
moveScaleMultiplier = MoveScaleMultiplier;
}
/// <summary>
/// Sets the move scale multiplier.
/// </summary>
/// <param name="moveScaleMultiplier">Move scale multiplier.</param>
public void SetMoveScaleMultiplier(float moveScaleMultiplier)
{
MoveScaleMultiplier = moveScaleMultiplier;
}
/// <summary>
/// Gets the rotation scale multiplier.
/// </summary>
/// <param name="rotationScaleMultiplier">Rotation scale multiplier.</param>
public void GetRotationScaleMultiplier(ref float rotationScaleMultiplier)
{
rotationScaleMultiplier = RotationScaleMultiplier;
}
/// <summary>
/// Sets the rotation scale multiplier.
/// </summary>
/// <param name="rotationScaleMultiplier">Rotation scale multiplier.</param>
public void SetRotationScaleMultiplier(float rotationScaleMultiplier)
{
RotationScaleMultiplier = rotationScaleMultiplier;
}
/// <summary>
/// Gets the allow mouse rotation.
/// </summary>
/// <param name="skipMouseRotation">Allow mouse rotation.</param>
public void GetSkipMouseRotation(ref bool skipMouseRotation)
{
skipMouseRotation = SkipMouseRotation;
}
/// <summary>
/// Sets the allow mouse rotation.
/// </summary>
/// <param name="skipMouseRotation">If set to <c>true</c> allow mouse rotation.</param>
public void SetSkipMouseRotation(bool skipMouseRotation)
{
SkipMouseRotation = skipMouseRotation;
}
/// <summary>
/// Gets the halt update movement.
/// </summary>
/// <param name="haltUpdateMovement">Halt update movement.</param>
public void GetHaltUpdateMovement(ref bool haltUpdateMovement)
{
haltUpdateMovement = HaltUpdateMovement;
}
/// <summary>
/// Sets the halt update movement.
/// </summary>
/// <param name="haltUpdateMovement">If set to <c>true</c> halt update movement.</param>
public void SetHaltUpdateMovement(bool haltUpdateMovement)
{
HaltUpdateMovement = haltUpdateMovement;
}
/// <summary>
/// Resets the player look rotation when the device orientation is reset.
/// </summary>
public void ResetOrientation()
{
if (HmdResetsY && !HmdRotatesY)
{
Vector3 euler = transform.rotation.eulerAngles;
euler.y = InitialYRotation;
transform.rotation = Quaternion.Euler(euler);
}
}
}
Related
I just finished a BreakOut style game but there is a bug where sometimes the ball gets stuck to the edges of the map with no direction or speed as shown in the screenshot
What I see is that it happens when the ball completely loses trajectory or speed, but could not solve the error
enter image description here
my code
public class Ball : MonoBehaviour
{
[SerializeField] Rigidbody2D rigidbody2D;
Vector2 moveDirection;
Vector2 currentVelocity;
float velocity=10;
//GameManager gameManager;
Transform paddle;
[SerializeField] AudioController audioController;
[SerializeField] AudioClip bounceSfx;
[SerializeField] AudioClip dieSfx;
public bool superBall;
[SerializeField] float superBallTime=10;
[SerializeField]float yMinSpeed = 10;
[SerializeField]TrailRenderer trailRenderer;
public bool SuperBall
{
get=> superBall;
set{
superBall=value;
if(superBall)
StartCoroutine(ResetSuperBall());
}
}
// Start is called before the first frame update
void Start()
{
//rigidbody2D = GetComponent<Rigidbody2D>();
//rigidbody2D.velocity = Vector2.up*velocity*Time.deltaTime;
GameManager.Instance = FindObjectOfType<GameManager>();
paddle = transform.parent;
}
// Update is called once per frame
void Update()
{
currentVelocity = rigidbody2D.velocity;
if (Mathf.Abs(currentVelocity.y) < 3 && Mathf.Abs(currentVelocity.y) < 3 && GameManager.Instance.ballOnGame)
{
velocity = 10;
rigidbody2D.velocity = Vector2.up * velocity ;
}
if (Mathf.Abs(currentVelocity.y) + Mathf.Abs(currentVelocity.y) < 10 && GameManager.Instance.ballOnGame)
{
velocity = 10;
rigidbody2D.velocity = Vector2.up * velocity ;
}
if (velocity <10 && GameManager.Instance.ballOnGame)
{
velocity = 10;
rigidbody2D.velocity = Vector2.up * velocity ;
}
if ((Input.GetKey(KeyCode.W) && GameManager.Instance.ballOnGame == false)||(Input.GetKey(KeyCode.Space) && GameManager.Instance.ballOnGame == false))
{
rigidbody2D.velocity = Vector2.up * velocity ;
transform.parent = null;
GameManager.Instance.ballOnGame = true;
rigidbody2D.isKinematic = false;
rigidbody2D.AddForce(new Vector3(velocity, velocity, 0));
if (!GameManager.Instance.GameStarted)
{
GameManager.Instance.GameStarted = true;
}
}
}
private void OnCollisionEnter2D(Collision2D collision)
{
if (collision.transform.CompareTag("Brick") && superBall)
{
rigidbody2D.velocity = currentVelocity;
return;
}
moveDirection=Vector2.Reflect(currentVelocity,collision.GetContact(0).normal);
if (Mathf.Abs(moveDirection.y) < yMinSpeed)
{
//permitir velocidad minima
moveDirection.y = yMinSpeed*Mathf.Sign(moveDirection.y);
}
rigidbody2D.velocity=moveDirection;
audioController.PlaySfx(bounceSfx);
if (collision.transform.CompareTag("BottomLimit"))
{
if(GameManager.Instance != null)
{
GameManager.Instance.PlayerLives--;
audioController.PlayDie(dieSfx);
if (GameManager.Instance.PlayerLives > 0)
{
rigidbody2D.velocity = Vector2.zero;
transform.SetParent(paddle);
transform.localPosition = new Vector2(0, 0.65f);
GameManager.Instance.ballOnGame = false;
}
}
}
}
IEnumerator ResetSuperBall()
{
trailRenderer.enabled = true;
yield return new WaitForSeconds(superBallTime);
trailRenderer.enabled = false;
GameManager.Instance.powerIsActive = false;
superBall = false;
}
}
This is a common issue with Rigidbodies at low velocities. The physics engine implements a Physics2D.velocityThreshold that is designed to dampen slow bounces and calm down a pile of Rigidbodies.
The default value for velocityThreshold is 1, meaning that the x or y component of the velocity that is slower will be floored to 0.
To resolve this issue you can simply lower the value to 0.001. You can do it in the Physcs2d tab located at Edit->ProjectSettings->Physics2d
I'm developing game like Hitman Go , and I need to find which waypoints are closest to my target(specific waypoint ) when enemy has alerted by rock or sound and etc.
I set some point for enemy and My enemy patrolling between waypoints ( 8 -> 6 -> 1-> 2-> 3-> 4-> 5 ) then reveres his path.
so, when I throw rock in waypoint number 18, I need to move enemy to this waypoint, but with closest way. imaging enemy can be any this waypoint when he get aleret ( 8,6,1,2,3,4,5 points).
Note 1: The distance between two points is same.
Note2: My game is in 3d not 2d.
I use this code to move my enemy step by step ( turn base ).
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class WaypointController : MonoBehaviour
{
public List<Transform> waypoints = new List<Transform>();
private Transform targetWaypoint;
private int targetWaypointIndex = 0;
private float minDistance = 0.1f;
private int lastWaypointIndex;
public bool reversePath;
// what easetype to use for iTweening
public iTween.EaseType easeType = iTween.EaseType.easeInOutExpo;
// how fast we move
public float moveSpeed = 1.5f;
// time to rotate to face destination
public float rotateTime = 0.5f;
// delay to use before any call to iTween
public float iTweenDelay = 0f;
// Use this for initialization
void Start()
{
lastWaypointIndex = waypoints.Count - 1;
targetWaypoint = waypoints[targetWaypointIndex];
}
public void EnemyTurn()
{
float distance = Vector3.Distance(transform.position, targetWaypoint.position);
CheckDistanceToWaypoint(distance);
// move toward the destinationPos using the easeType and moveSpeed variables
iTween.MoveTo(gameObject, iTween.Hash(
"x", targetWaypoint.position.x,
"y", targetWaypoint.position.y,
"z", targetWaypoint.position.z,
"delay", iTweenDelay,
"easetype", easeType,
"speed", moveSpeed
));
}
void CheckDistanceToWaypoint(float currentDistance)
{
if (currentDistance <= minDistance)
{
targetWaypointIndex++;
UpdateTargetWaypoint();
}
}
void UpdateTargetWaypoint()
{
if (targetWaypointIndex > lastWaypointIndex)
{
if (reversePath)
{
waypoints.Reverse();
}
targetWaypointIndex = 1;
}
targetWaypoint = waypoints[targetWaypointIndex];
}
}
Since you asked in the comments for a non-A* solution & I was bored :)
Naive DFS pathfinder with very simple pruning.
Brute force and very wasteful both memory & CPU wise.
For a game similar to Hitman Go / Lara Croft Go - I would use this code and not a navmesh / A*.
For a RTS / FPS or any AI intensive games, I would definitely not use this solution.
public class GridPathfinder
{
// Not thread safe
private int? _currentShortestPath;
/// <summary>
/// Finds shortest path from cell A to B
/// </summary>
/// <returns>Shortest found path; null if found no path.</returns>
public IList<Node> GetShortestPath(Node a, Node b)
{
_currentShortestPath = null;
return GetShortestPathInternal(a, b, new List<Node>());
}
private IList<Node> GetShortestPathInternal(Node #from, Node to, List<Node> currentPath)
{
// Sanity
if (currentPath.Contains(from))
{
return null;
}
// Prune
if (_currentShortestPath.HasValue && currentPath.Count + 1 >= _currentShortestPath)
{
return null;
}
currentPath.Add(from);
if (from == to)
{
return currentPath;
}
// Check neighbors recursively
IList<Node> foundShortestPath = null;
foreach (var connectedCell in from.ConnectedCells)
{
var cellPath = GetShortestPathInternal(connectedCell, to, new List<Node>(currentPath));
if (cellPath == null || foundShortestPath != null && cellPath.Count >= foundShortestPath.Count)
{
continue;
}
foundShortestPath = cellPath;
}
// Update shortest path for future pruning
if (foundShortestPath != null && (!_currentShortestPath.HasValue || _currentShortestPath > foundShortestPath.Count))
{
_currentShortestPath = foundShortestPath.Count;
}
return foundShortestPath;
}
}
public class Node
{
private readonly HashSet<Node> _connectedCells = new HashSet<Node>();
public IEnumerable<Node> ConnectedCells => _connectedCells;
/// <summary>
/// Add a connection
/// </summary>
/// <param name="toAdd">Node to add</param>
/// <param name="isTwoWay">Should add a connection from target node to this node</param>
public void AddConnection(Node toAdd, bool isTwoWay=true)
{
if (toAdd == null || toAdd == this)
{
throw new Exception("Invalid connection attempted");
}
// Attempt to add
if (!_connectedCells.Add(toAdd))
{
return;
}
if (!isTwoWay) return;
toAdd.AddConnection(this);
}
}
So I am developing an online multiplayer FPS game for my SDD major work, and I have run into a problem. Below is the movement code for my player. I am trying to implement strafing and bunnyhopping into my game, and so I setup a test environment within my project and I managed to get everything working. The only problem was that after I tried to put this back into my main project, it stopped working.
The main problem is that the jumping only works sometimes. The player only jumps a very small amount, and sometimes stay there, meaning that there is no friction as the player is stuck off the ground. He also seems to phase beneath the ground a tiny bit, but the collider on him shouldn't let that happen. I have tried to remove the code that makes downward falls faster, but that only fixes it sometimes.
Code link: https://pastebin.com/cLkemQhX
public class PlayerMovement: MonoBehaviourPun
{
[Header("Movement Settings")]
public float maxVelocityGround = 15f;
public float maxVelocityAir = 10f;
public float groundAccelerate = 90f;
public float airAccelerate = 180f;
public float fallMultiplier = 1.2f;
public float lookSens = 8f;
public float slowDrag = 0;
public float thrusterForce = 7f;
public float friction = 10f;
private float _friction = 0f;
[Header("Rotation")]
float xRot = 0F;
float yRot = 0F;
float minY = -90f;
float maxY = 90f;
Quaternion originalRotation;
//More Movement Variables
private float distToGround;
private Vector3 _velocity;
private Vector2 xyVelocity;
[Header("References")]
//public Text grounded;
//public Text velocity;
public Camera cam;
private Move motor;
private Rigidbody rb;
private CapsuleCollider collidr;
private GameObject rayPoint;
//private PlayerSetup playerSetup;
//Booleans
private bool jumpy = false;
void Start()
{
_friction = friction;
//Locks the cursor to the middle of the screen, and hides it from view
Cursor.lockState = CursorLockMode.Locked;
Cursor.visible = false;
//These attatch the correct objectss to their references in the script, defined above
motor = GetComponent<Move>();
rb = GetComponent<Rigidbody>();
collidr = GetComponent<CapsuleCollider>();
rayPoint = GameObject.Find("point");
//playerSetup = GetComponent<PlayerSetup>();
//Sets the distance to the ground from the center of the collider, used in determining whe nthe player is on the ground
distToGround = collidr.bounds.extents.y;
if (GetComponent<Rigidbody>())
GetComponent<Rigidbody>().freezeRotation = true;
originalRotation = transform.localRotation;
}
void FixedUpdate()
{
//Debug function that shows a visual representation of when the player is on the ground
//string a = isGrounded().ToString();
//grounded.GetComponent<Text>().text = a;
//Finds the Velocity in the x plane. Also used in debug, as it shows it on screen
//xyVelocity = new Vector2(rb.velocity.x, rb.velocity.z);
//velocity.GetComponent<Text>().text = xyVelocity.magnitude.ToString("0.000");
//This statement checks if the player both is on the ground, and has requested to jump. If so it will jump
//while also not allowing multiple jumps while in the air. If the player holds it down, he will jump as soon
//as he touches the ground, avoiding friction and allowing the player to bunnyhop
if (Input.GetKey("space") && isGrounded())
{
rb.AddForce(Vector3.up * thrusterForce, ForceMode.Impulse);
jumpy = true;
}
//rb.AddForce(Jump(), ForceMode.Impulse);
//This makes you fall faster than you rise, and make jumping feel nicer overall.
if (rb.velocity.y < 0)
{
rb.velocity += Vector3.up * Physics.gravity.y * fallMultiplier * Time.deltaTime;
}
//Gets the input from the axis'
float input_y = Input.GetAxis("Vertical");
float input_x = Input.GetAxis("Horizontal");
//Calculates the direction we want to move in, taking into account mouse movement to allow for strafing
Vector3 accelDir = (transform.forward * input_y + transform.right * input_x).normalized;
//Checks if we are not pressing any inputs, and makes us decelerate faster, to make moving feel more snappy
decelerate(accelDir);
//This code adjusts the vector to be projected onto the plane that we are currently moving on. Makes strafing better
RaycastHit hit;
Physics.Raycast(collidr.center, Vector3.down, out hit, 1000);
accelDir = Vector3.ProjectOnPlane(accelDir, hit.normal).normalized;
//Finds the current velocity of our RIgidBody
Vector3 curVel = rb.velocity;
//Determines whether or not we want to use the air movement(ignore friction) or not.
//The boolean checks if we have just jumped, so while we are still on the ground, we don't want to calculate friciton
if (isGrounded() && jumpy == false)
{
_velocity = MoveGround(accelDir, curVel);
}
else
{
_velocity = MoveAir(accelDir, curVel);
}
//Apply Movement
rb.velocity = _velocity;
//These call the rotation functions below, one rotates the camera in the y plane, the other the rigidbody in the x plane, which has the camera as a child
cameraRotate();
rbRotate();
jumpy = false;
}
private Vector3 MoveGround(Vector3 accelDir, Vector3 prevVelocity)
{
// Apply Friction
float speed = prevVelocity.magnitude;
if (speed != 0) // To avoid divide by zero errors
{
float drop = speed * _friction * Time.fixedDeltaTime;
prevVelocity *= Mathf.Max(speed - drop, 0) / speed; // Scale the velocity based on friction.
}
return Accelerate(accelDir, prevVelocity, groundAccelerate, maxVelocityGround);
}
private Vector3 MoveAir(Vector3 accelDir, Vector3 prevVelocity)
{
return Accelerate(accelDir, prevVelocity, airAccelerate, maxVelocityAir);
}
private Vector3 Accelerate(Vector3 accelDir, Vector3 prevVelocity, float accelerate, float max_velocity)
{
float projVel = Vector3.Dot(prevVelocity, accelDir); // Vector projection of Current velocity onto accelDir.
float accelVel = accelerate * Time.fixedDeltaTime; // Accelerated velocity in direction of movment
// If necessary, truncate the accelerated velocity so the vector projection does not exceed max_velocity
if (projVel + accelVel > max_velocity)
{
accelVel = max_velocity - projVel;
};
return prevVelocity + accelDir * accelVel;
}
//Function to check if we are on the ground
public bool isGrounded()
{
return Physics.Raycast(collidr.bounds.center, Vector3.down, distToGround);
//Below is a capsule cast, it would be better to implement because it has a thickness
//return Physics.CheckCapsule(collider.bounds.center, new Vector3(collider.bounds.center.x, collider.bounds.min.y, collider.bounds.center.z), collider.radius * 0.9f);
}
/// <summary>
/// decelerates us faster when not moving
/// </summary>
/// <param name="input"></param>
public void decelerate(Vector3 input)
{
if (input == Vector3.zero)
{
_friction = 10f * friction;
}
else
{
_friction = friction;
}
}
/// <summary>
/// This function is the camera rotation function
/// </summary>
public void cameraRotate()
{
//Get the input from the mouse and multiply it by sensitivity so it can be adjusted from ingame
yRot += Input.GetAxis("Mouse Y") * lookSens;
//Clamp it so that we cant just keep spinning in the Y direction
yRot = clamp(yRot, minY, maxY);
//Calculate the quaternion using the amount of rotation found before. We use the negative mouse input as the amount
//of rotation, and then specify that we want this rotation to be around the x axis. It seems counter intuitive, but this is the way to do it
Quaternion yRotAngle = Quaternion.AngleAxis(-yRot, Vector3.right);
//Apply this rotation to the cameras transform
cam.transform.localRotation = originalRotation * yRotAngle;
}
/// <summary>
/// Basically the same as above, but we dont need to clamp it because we want to be able to forever spin to the left and right
/// </summary>
public void rbRotate()
{
xRot += Input.GetAxis("Mouse X") * lookSens;
Quaternion xRotAngle = Quaternion.AngleAxis(xRot, Vector3.up);
rb.transform.localRotation = originalRotation * xRotAngle;
}
/// <summary>
/// just clamps the angle we input between the next 2 floats
/// </summary>
/// <param name="angle">the float representation of the angle</param>
/// <param name="min">the min that the angle can be</param>
/// <param name="max">you got it by now right?></param>
/// <returns></returns>
private float clamp(float angle, float min, float max)
{
return Mathf.Clamp(angle, min, max);
}
}
I'm new at programming. I started a Unity3D course at udemy, I already finished the course, but I'm trying to add a buff to my game. What I want is when my player gets that buff, his shot speed inscreases, I tried to do it but im getting this error when I collide with it
NullReferenceException: Object reference not set to an instance of an object
Powerup.OnTriggerEnter2D (UnityEngine.Collider2D other) (at Assets/Galaxy Shooter/Scripts/Powerup.cs:54)
EDIT
Album With usefull images
Player
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Player : MonoBehaviour {
public bool canTripleShoot = false;
public bool movSpeedBoost = false;
public bool shield = false;
[SerializeField]
private GameObject _laserPrefabs;
[SerializeField]
private GameObject _tripleShootPrefab;
[SerializeField]
private GameObject _shieldGameObject;
[SerializeField]
private GameObject _explosionPrefab;
[SerializeField]
private float _speed = 5.0f;
[SerializeField]
private GameObject[] _engines;
[SerializeField]
private float _fireRate = 0.25f;
private float _canFire = 0.0f;
public int playerHp = 3;
public int _hitcount = 0;
private UIManager _uiManager;
private GameManager _gameManager;
private SpawnManager _spawnManager;
private AudioSource _audioSource;
// Use this for initialization
void Start () {
_audioSource = GetComponent<AudioSource>();
_spawnManager = GameObject.Find("Spawn_Manager").GetComponent<SpawnManager>();
_uiManager = GameObject.Find("Canvas").GetComponent<UIManager>();
_gameManager = GameObject.Find("GameManager").GetComponent<GameManager>();
transform.position = new Vector3(0, 0, 0);
if(_uiManager != null)
{
_uiManager.UpdateLives(playerHp);
}
if(_spawnManager != null)
{
_spawnManager.StartSpawn();
}
}
// Update is called once per frame
void Update ()
{
Movement();
//ativar ao pressionar espaço ou botão esquerdo do mouse
if (Input.GetKeyDown(KeyCode.Space) || Input.GetMouseButton(0))
{
Shoot();
}
}
//renderização e cooldown dos tiros
private void Shoot()
{
if (Time.time > _canFire)
{
_audioSource.Play();
if (canTripleShoot== true)
{
Instantiate(_tripleShootPrefab, transform.position, Quaternion.identity);
}
else
{
Instantiate(_laserPrefabs, transform.position + new Vector3(0, 0.95f, 0), Quaternion.identity);
}
_canFire = Time.time + _fireRate;
}
}
//calculo de dano
public void Damage()
{
if(shield == true)
{
shield = false;
_shieldGameObject.SetActive(false);
return;
}
_hitcount++;
if(_hitcount == 1)
{
_engines[0].SetActive(true);
}
if(_hitcount == 2)
{
_engines[1].SetActive(true);
}
playerHp--;
_uiManager.UpdateLives(playerHp);
if(playerHp < 1)
{
Instantiate(_explosionPrefab, transform.position, Quaternion.identity);
_gameManager.gameOver = true;
_uiManager.ShowTitleScreen();
Destroy(this.gameObject);
}
}
public void ShieldUp()
{
shield = true;
_shieldGameObject.SetActive(true);
}
//controle da velocidade de movimento e teleporte
private void Movement()
{
float controleHorizontal = Input.GetAxis("Horizontal");
float controleVertical = Input.GetAxis("Vertical");
//velocidade de movimento
if(movSpeedBoost == true)
{
transform.Translate(Vector3.up * _speed * controleVertical * Time.deltaTime * 2.0f);
transform.Translate(Vector3.right * _speed * controleHorizontal * Time.deltaTime * 2.0f);
}else
{
transform.Translate(Vector3.up * _speed * controleVertical * Time.deltaTime);
transform.Translate(Vector3.right * _speed * controleHorizontal * Time.deltaTime);
}
//limita jogar até o centro da tela
if (transform.position.y > 0)
{
transform.position = new Vector3(transform.position.x, 0, 0);
}
//limita jogar até a borda inferior
else if (transform.position.y < -4.2f)
{
transform.position = new Vector3(transform.position.x, -4.2f, 0);
}
//teleporta jogar se sair da tela na horizontal
else if (transform.position.x < -9.45f)
{
transform.position = new Vector3(9.45f, transform.position.y, 0);
}
else if (transform.position.x > 9.45f)
{
transform.position = new Vector3(-9.45f, transform.position.y, 0);
}
}
//duração triple shot
public IEnumerator TripleShotPowerDownRoutine()
{
yield return new WaitForSeconds(5.0f);
canTripleShoot = false;
}
public void TripleShotPowerUpOn()
{
canTripleShoot = true;
StartCoroutine(TripleShotPowerDownRoutine());
}
//duração boost de movimento
public IEnumerator MovSpeedBoostDownRoutine()
{
yield return new WaitForSeconds(5.0f);
movSpeedBoost = false;
}
//ativa boost de movimento e inicia contagem de duração
public void MovSpeedBoost()
{
movSpeedBoost = true;
StartCoroutine(MovSpeedBoostDownRoutine());
}
}
Laser
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Laser : MonoBehaviour {
[SerializeField]
public float _speed = 10.0f;
[SerializeField]
public bool _laserBoost = false;
// Use this for initialization
void Start () {
_laserBoost = false;
if (_laserBoost == true)
{
_speed = 100f;
}
}
// Update is called once per frame
void Update () {
//código gigante e dificil de decifrar ~irony
transform.Translate(Vector3.up * _speed * Time.deltaTime);
if (transform.position.y > 6f)
{
if(transform.parent != null)
{
Destroy(transform.parent.gameObject);
}
Destroy(gameObject);
}
}
public IEnumerator LaserBoostDuration()
{
yield return new WaitForSeconds(10f);
_laserBoost = false;
}
public void LaserBoost()
{
_laserBoost = true;
StartCoroutine(LaserBoostDuration());
}
}
Powerup
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Powerup : MonoBehaviour
{
[SerializeField]
private float _speed = 3.0f;
[SerializeField]
private int powerupID;
[SerializeField]
private AudioClip _clip;
// Update is called once per frame
void Update ()
{
//movimenta o powerup para baixo
transform.Translate(Vector3.down * _speed * Time.deltaTime);
//destroy o power ao sair da tela
if (transform.position.y <-7)
{
Destroy(this.gameObject);
}
}
private void OnTriggerEnter2D(Collider2D other)
{
if(other.tag == "Player")
{
//acessa o player
Player player = other.GetComponent<Player>();
if(player != null)
{
if(powerupID == 0)
{
//ativa tripleshoot
player.TripleShotPowerUpOn();
}
else if(powerupID == 1)
{
//ativa speedboost
player.MovSpeedBoost();
}
else if(powerupID == 2)
{
//ativar shield
player.ShieldUp();
}
else if (powerupID == 3)
{
Laser laser = GameObject.Find("laser").GetComponent<Laser>();
laser.LaserBoost();
}
}
//detroy powerup
AudioSource.PlayClipAtPoint(_clip, transform.position);
Destroy(this.gameObject);
}
}
}
The error is occuring at
laser.LaserBoost();
One of the two:
1) you don't have a object named "laser" in Scene hierarchy;
2) this object exists but doesn't have a component of type Laser attached to it.
Edit: Now that I saw your image, I can confirm it is the case 1) above. You have a Prefab named "laser", but is doesn't exist in the Scene hierarchy. If you want it to come to existence only when needed, you must instantiate the Prefab in scene.
If you want to search for the Prefab by its name, there is a way, but you'll need to have a folder named Resources inside another named Assets... More info here
Instead, I suggest you another approach. First, you will need a reference to your Prefab in some object, depending on the logic of your program. You seem to have a GameManager class, there could be a good place. Add a new field inside there (if it is the case) like this:
[SerializeField]
public Laser laser
// (...)
Then, change the code that generates the error. GameObject.Find tries to find an object that already exists in scene. In your case, you want to instantiate a clone of a Prefab, by passing a reference to it. Something like this:
else if (powerupID == 3)
{
// I don't know for sure how can you access your GameManager in your program. I will suppose your player have a reference to it.
// You shall change the position depending on your game logic
Laser laserClone = (Laser) Instantiate(player.gameManager.laser, player.transform.position, player.transform.rotation);
laserClone.LaserBoost();
}
Now, select the object in Scene that will have the reference (again, I am supposing it is gameManager) to see its inspector, than fill the laser field with a reference to your Prefab that has a Laser component. Just be sure the clone object will be destroyed when it is not needed.
But... To be very honest, I don't think you will get the result you are expecting anyway. If what you want is just faster shoot rate, the way you're trying to do it now seems pretty convoluted to me. Why don't you do it just like the triple shoot you have? Add a flag inside your player, when it is true the fireRate value changes.
I've got a player controller that should work over UNET. I must not understand something though as any remote players joining a game can't control their character.
The hosting local player can control his/her character just fine.
Basically the way I think this is working is that in Update the local player can press keys. Those keypresses issue Commands to the server where synced bools are set.
In FixedUpdate the server moves the Rigidbody around based on the set bools. On the player object I have a NetworkTransform so any movement the server does should be sent back to the client.
using UnityEngine;
using UnityEngine.Networking;
using System.Collections;
[RequireComponent(typeof(NetworkIdentity))]
public class PlayerController : NetworkBehaviour {
public GameObject NormalBullet;
public Vector3 size = new Vector3(0.25f, 0.25f, 0.25f);
private float speed = 8;
private float angularSpeed = 35;
private float jumpForce = 10;
private Rigidbody _rigidbody;
private Map _map;
private NHNetworkedPool _pool;
private bool _active = false;
private Vector3 _lastPosition;
[SyncVar]
private bool _moveForward;
[SyncVar]
private bool _moveBackward;
[SyncVar]
private bool _turnLeft;
[SyncVar]
private bool _turnRight;
[SyncVar]
private bool _jump;
[SyncVar]
private bool _isgrounded;
[SyncVar]
private bool _isFireing;
void Awake () {
Messenger.AddListener ("MAP_LOADED", OnMapLoaded);
_rigidbody = gameObject.GetComponent<Rigidbody> ();
_map = GameObject.Find ("Map").GetComponent<Map> ();
Physics.IgnoreLayerCollision(LayerMask.NameToLayer("Players"), LayerMask.NameToLayer("Players"), true);
}
override public void OnStartClient () {
_rigidbody.position = new Vector3 (-100, -100, -100);
if (NetworkServer.active) {
_pool = FindObjectOfType<NHNetworkedPool> ();
}
}
/// <summary>
/// Once the board is built, hookup the camera if this is the local player
/// and set the player as active.
/// </summary>
void OnMapLoaded () {
if (isLocalPlayer) {
// Hook up the camera
PlayerCamera cam = Camera.main.GetComponent<PlayerCamera>();
cam.target = transform;
// Move the player to the it's spawn location
CmdSpawn();
}
// Set the player as active
_active = true;
}
/// <summary>
/// Only and active local player should be able to
/// issue commands for the player
/// </summary>
void Update () {
if (!isLocalPlayer || !_active) {
return;
}
if (Input.GetKeyDown ("up")) {
CmdSetMoveForward (true);
}
if (Input.GetKeyUp ("up")) {
CmdSetMoveForward (false);
}
if (Input.GetKeyDown ("down")) {
CmdSetMoveBackward (true);
}
if (Input.GetKeyUp ("down")) {
CmdSetMoveBackward (false);
}
if (Input.GetKeyDown ("left")) {
CmdSetTurnLeft (true);
}
if (Input.GetKeyUp ("left")) {
CmdSetTurnLeft (false);
}
if (Input.GetKeyDown ("right")) {
CmdSetTurnRight (true);
}
if (Input.GetKeyUp ("right")) {
CmdSetTurnRight (false);
}
if (Input.GetKeyDown (KeyCode.Space)) {
CmdSetJump (true);
}
if (Input.GetKeyUp (KeyCode.Space)) {
CmdSetJump (false);
}
if (Input.GetKeyDown (KeyCode.LeftShift)) {
CmdSetShooting(true);
}
if (Input.GetKeyUp (KeyCode.LeftShift)) {
CmdSetShooting(false);
}
}
/// <summary>
/// Only the server should update the player's location
/// the transform is synced to the clients
/// </summary>
void FixedUpdate () {
if (!isServer) {
return;
}
if (_moveForward) {
float moveAmount = speed * Time.deltaTime;
_rigidbody.MovePosition(_rigidbody.position + _rigidbody.transform.forward * moveAmount);
}
if (_moveBackward) {
float moveAmount = (-speed * 0.6f) * Time.deltaTime;
_rigidbody.MovePosition(_rigidbody.position + _rigidbody.transform.forward * moveAmount);
}
if (_turnLeft) {
Quaternion rotateAmount = Quaternion.Euler(new Vector3(0f, -angularSpeed, 0f) * Time.deltaTime);
_rigidbody.MoveRotation(_rigidbody.rotation * rotateAmount);
}
if (_turnRight) {
Quaternion rotateAmount = Quaternion.Euler(new Vector3(0f, angularSpeed, 0f) * Time.deltaTime);
_rigidbody.MoveRotation(_rigidbody.rotation * rotateAmount);
}
if (_jump && _isgrounded) {
_rigidbody.AddForce(Vector3.up * 250);
}
}
void OnCollisionStay (Collision collision) {
if(collision.gameObject.tag.ToUpper() == "GROUND") {
_isgrounded = true;
}
}
void OnCollisionExit (Collision collision) {
if(collision.gameObject.tag.ToUpper() == "GROUND") {
_isgrounded = false;
}
}
/// <summary>
/// Client -> Server
/// Move the player to a spawn location
/// </summary>
void CmdSpawn() {
_rigidbody.position = _map.GetPlayerSpawn();
_rigidbody.velocity = Vector3.zero;
}
/// <summary>
/// Client -> Server
/// Set the forward move of the player on/off
/// </summary>
[Command]
void CmdSetMoveForward (bool active) {
_moveForward = active;
}
/// <summary>
/// Client -> Server
/// Set the backward of the player on/off
/// </summary>
[Command]
void CmdSetMoveBackward (bool active) {
_moveBackward = active;
}
/// <summary>
/// Client -> Server
/// Set the left turn of the player on/off
/// </summary>
[Command]
void CmdSetTurnLeft (bool active) {
_turnLeft = active;
}
/// <summary>
/// Client -> Server
/// Set the right turn of the player on/off
/// </summary>
[Command]
void CmdSetTurnRight (bool active) {
_turnRight = active;
}
/// <summary>
/// Client -> Server
/// Set the jumpping of the player on/off
/// </summary>
[Command]
void CmdSetJump (bool active) {
_jump = active;
}
/// <summary>
/// Client -> Server
/// Set shooting weapon on/off
/// </summary>
[Command]
void CmdSetShooting (bool active) {
_isFireing = true;
}
}
You should not do the movement on the server. Rewrite it so that the movement is calculated and executed on the client.
Then add an NetworkTransform component to the player and it should work.
Only the Fire method has to be a Command. But because I don't know what actually happens when _isFireing = true I can't tell you what you should write exactly ;)
EDIT: You also need a NetworkIdentity component on the player if you don't have one