Hello,
I am using Mirror in my unity project, and I want to incorporate shooting via equipping guns. The variable raycastTransform and sealTestController refers to the camera, and assigned upon equip.
The issue is that once I debug its forward orientation on the client, it is stuck on a constant y value of -0.53 with x and z values being approximately 0.
On the host, it’s fine. Shooting bullets works normally with the camera looking forward.
Why?
Here is my code:
void Start()
{
startRotation = transform.localEulerAngles;
currentAmmo = maxAmmo;
if (gunType == GunType.Grapple) {
originalHookPos = hook.transform.localPosition;
originalHookRot = hook.transform.localRotation;
}
startPosition = transform.localPosition;
}
void Update()
{
if (!isOwned) { return; }
targetRotation = Vector3.Lerp(targetRotation, Vector3.zero, returnSpeed * Time.deltaTime);
currentRotation = Vector3.Slerp(currentRotation, targetRotation, snappiness * Time.fixedDeltaTime);
transform.localRotation = Quaternion.Euler(currentRotation);
if (sealTestController != null && gunType != GunType.Grapple && sealTestController.isFireLongPressed)
transform.parent.forward = raycastTransform.forward;
if (gunType != GunType.Grapple) {
if (sealTestController != null) {
}
else {
targetRotation = Vector3.Lerp(targetRotation, startRotation, returnSpeed * Time.deltaTime);
currentRotation = Vector3.Slerp(currentRotation, targetRotation, snappiness * Time.fixedDeltaTime);
transform.localRotation = Quaternion.Euler(currentRotation);
if (raycastTransform != null)
transform.parent.forward = raycastTransform.forward;
}
}
if (sealTestController != null) {
if (gunType == GunType.Automatic) {
if (sealTestController.isFireLongPressed && Time.time >= nextTimeToFire) {
nextTimeToFire = Time.time + 1f / fireRate;
CmdShoot();
}
}
if (gunType == GunType.Minigun) {
if (sealTestController.isFireLongPressed) {
if (Time.time >= nextTimeToFire) {
nextTimeToFire = Time.time + 1f / fireRate;
CmdShoot();
}
if (currentAmmo == 0)
currentMinigunRotationSpeed = Mathf.Lerp(currentMinigunRotationSpeed, 0f, Time.deltaTime * minigunAccelerationRate);
else
currentMinigunRotationSpeed = Mathf.Lerp(currentMinigunRotationSpeed, rotationSpeed, Time.deltaTime * minigunAccelerationRate);
}
else {
currentMinigunRotationSpeed = Mathf.Lerp(currentMinigunRotationSpeed, 0f, Time.deltaTime * minigunAccelerationRate);
}
rotationPartMinigun.transform.Rotate(Vector3.right, currentMinigunRotationSpeed * Time.deltaTime);
}
if (gunType == GunType.Pistol) {
if (sealTestController.isFirePressed) {
CmdShoot();
}
}
if (gunType == GunType.Sniper) {
if (sealTestController.isFirePressed) {
CmdShoot();
}
}
if (gunType == GunType.Shotgun) {
if (sealTestController.isFirePressed) {
CmdShoot();
}
}
if (gunType == GunType.RPG) {
if (sealTestController.isFirePressed) {
CmdShootRPG();
}
}
if (gunType == GunType.Grapple) {
if (sealTestController.isFirePressed && !IsGrappling()) {
CmdStartGrapple();
}
else if (!sealTestController.isFirePressed && IsGrappling()){
CmdStopGrapple();
}
if (IsGrappling()) {
grapplePoint = hit.collider.ClosestPoint(hit.point);
player.GetComponent<SealTestController>().EnableRagdoll();
transform.parent.LookAt(GetGrapplePoint());
}
}
if (sealTestController.isReloadPressed) {
CmdReload();
}
if (isReloading) {
timePassed += Time.deltaTime;
float normalizedTime = Mathf.Clamp01(timePassed / duration);
float scale = scaleCurve.Evaluate(normalizedTime);
if (gunType == GunType.RPG)
placeHolderRocket.transform.localScale = new Vector3(scale, scale, scale);
if (timePassed >= duration)
{
timePassed = 0f;
if (gunType == GunType.RPG)
placeHolderRocket.transform.localScale = Vector3.one;
isReloading = false;
}
}
}
}
[Command]
void CmdShoot() {
if (currentAmmo <= 0) {
Debug.LogWarning("No ammo left!");
return;
}
if (raycastTransform == null) {
Debug.LogError("RaycastTransform is not assigned!");
return;
}
RaycastHit hit;
Vector3 screenCenter = new Vector3(Screen.width / 2f, Screen.height / 2f, 0f);
Ray ray;
if (sealTestController != null) {
ray = raycastTransform.GetComponent<Camera>().ScreenPointToRay(screenCenter);
sealTestController.ScreenShake(ray.direction, sealTestController.recoilShakeAmount);
}
else {
ray = new Ray(raycastTransform.position, raycastTransform.forward);
}
if (ray.Equals(null)) {
Debug.LogError("Failed to create ray for shooting!");
return;
}
Vector3 direction = GetDirection();
if (Physics.Raycast(raycastTransform.position, direction, out hit, range, whatIsShooting)) {
if (hit.transform.GetComponent<Barrel>()) {
hit.transform.GetComponent<Barrel>().Damage(damageToObject);
if (sealTestController != null) {
if (Vector3.Distance(player.transform.position, hit.transform.position) > hit.transform.GetComponent<Barrel>().bomb.explosionRadius) {
sealTestController.ScreenShake(ray.direction, sealTestController.explosionShakeAmount);
}
}
}
if (hit.collider.tag.Contains("Guard")) {
hit.transform.GetComponent<Guard>().Damage(damageToObject);
if (sealTestController != null && hit.transform.GetComponent<Guard>().guardState != Guard.GuardState.Fleeing) {
hit.transform.GetComponent<Guard>().sealToChase = sealTestController.gameObject;
hit.transform.GetComponent<Guard>().guardState = Guard.GuardState.Running;
}
Debug.Log("Damage");
}
if (hit.collider.GetComponent<Breakable>()) {
hit.collider.GetComponent<Breakable>().RpcBreak();
}
if (hit.collider.GetComponent<SealTestController>()) {
hit.collider.GetComponent<SealTestController>().ScreenShake(ray.direction, hit.collider.GetComponent<SealTestController>().recoilShakeAmount);
}
if (hit.rigidbody != null) {
hit.rigidbody.AddForce(-hit.normal * impactForce);
}
}
RpcShoot(hit.point, hit.normal);
currentAmmo--;
}
[ClientRpc]
void RpcShoot(Vector3 hitPoint, Vector3 hitNormal) {
muzzleFlash.Play();
if (gunType == GunType.Minigun)
bulletParticles.Play();
TrailRenderer trail = Instantiate(BulletTrail, gunTip.position, Quaternion.identity);
if (hitPoint != Vector3.zero)
StartCoroutine(SpawnTrail(trail, hitPoint, hitNormal, true));
else
StartCoroutine(SpawnTrail(trail, gunTip.position + GetDirection() * 100, Vector3.zero, false));
}
[Command]
void CmdShootRPG() {
Debug.Log("ShootRPG");
if (currentAmmo <= 0) { return; }
Ray ray = new Ray(raycastTransform.position, raycastTransform.forward);
if (sealTestController != null)
sealTestController.ScreenShake(ray.direction, sealTestController.recoilShakeAmount);
GameObject spawnedRocket = Instantiate(rocket, rocketSpawn.position, raycastTransform.rotation);
NetworkServer.Spawn(spawnedRocket);
spawnedRocket.GetComponent<Rigidbody>().velocity = raycastTransform.forward * rocketLaunchForce;
if (sealTestController != null)
spawnedRocket.GetComponent<Rocket>().sealTestController = sealTestController;
placeHolderRocket.SetActive(false);
RpcShootRPG();
currentAmmo--;
}
[ClientRpc]
public void RpcShootRPG() {
muzzleFlash.Play();
}
[Command]
void CmdReload() {
RpcReload();
}
[ClientRpc]
public void RpcReload() {
Debug.Log("Reloading");
currentAmmo = maxAmmo;
if (gunType == GunType.RPG) {
placeHolderRocket.SetActive(true);
}
isReloading = true;
}
private Vector3 GetDirection()
{
Vector3 direction = raycastTransform.forward;
Debug.Log($"Initial Direction: {direction}");
if (sealTestController != null) {
if (gunType != GunType.Shotgun) {
if (!sealTestController.isAiming) {
direction += new Vector3(
Random.Range(-BulletSpreadVariance.x, BulletSpreadVariance.x),
Random.Range(-BulletSpreadVariance.y, BulletSpreadVariance.y),
Random.Range(-BulletSpreadVariance.z, BulletSpreadVariance.z)
);
}
}
else {
direction += new Vector3(
Random.Range(-BulletSpreadVariance.x, BulletSpreadVariance.x),
Random.Range(-BulletSpreadVariance.y, BulletSpreadVariance.y),
Random.Range(-BulletSpreadVariance.z, BulletSpreadVariance.z)
);
}
}
else {
if (guard != null) {
direction += new Vector3(
Random.Range(-InsaneBulletSpreadVariance.x, InsaneBulletSpreadVariance.x),
Random.Range(-InsaneBulletSpreadVariance.y, InsaneBulletSpreadVariance.y),
Random.Range(-InsaneBulletSpreadVariance.z, InsaneBulletSpreadVariance.z)
);
}
else {
direction += new Vector3(
Random.Range(-BulletSpreadVariance.x, BulletSpreadVariance.x),
Random.Range(-BulletSpreadVariance.y, BulletSpreadVariance.y),
Random.Range(-BulletSpreadVariance.z, BulletSpreadVariance.z)
);
}
}
Debug.Log($"Direction with Spread: {direction}");
direction.Normalize();
Debug.Log($"Calculated shooting direction: {direction}");
return direction;
}
private IEnumerator SpawnTrail(TrailRenderer Trail, Vector3 HitPoint, Vector3 HitNormal, bool MadeImpact)
{
// This has been updated from the video implementation to fix a commonly raised issue about the bullet trails
// moving slowly when hitting something close, and not
Vector3 startPosition = Trail.transform.position;
float distance = Vector3.Distance(Trail.transform.position, HitPoint);
float remainingDistance = distance;
while (remainingDistance > 0)
{
Trail.transform.position = Vector3.Lerp(startPosition, HitPoint, 1 - (remainingDistance / distance));
remainingDistance -= BulletSpeed * Time.deltaTime;
yield return null;
}
Trail.transform.position = HitPoint;
if (NetworkServer.active)
{
GameObject impact = Instantiate(impactParticleSystem, HitPoint, Quaternion.LookRotation(HitNormal));
NetworkServer.Spawn(impact);
}
else
{
Debug.LogWarning("Tried to spawn impact effect without an active server.");
}
Destroy(Trail.gameObject, Trail.time);
}
Thank you