Function fires in wrong switch case - c#

I'm trying to implement a "lazy state machine" using enums for simple enemy AI but for some reason the logic doesn't work as intended.
I need my enemy to stop from time to time to be in Idle state. But when Idle switch fires, my enemy continues to move despite another state condition for moving script.
What's wrong with my script logic?
void Update()
{
Debug.Log(state);
onGround = Physics2D.Raycast(gameObject.transform.position, Vector2.down, groundLength, groundLayer);
Debug.DrawRay(gameObject.transform.position, Vector2.down * 1f, Color.red);
isAnythingThere = Physics2D.Raycast(wallDetection.position, Vector2.right * speed, 0.3f, sideInfo);
RaycastHit2D groundInfo = Physics2D.Raycast(groundDetection.position, Vector2.down, distance);
RaycastHit2D isPlayerInSight = Physics2D.Raycast(wallDetection.position, Vector2.right * speed, 3f, playerLayer);
switch (state)
{
default:
case State.patrol:
if ((groundInfo.collider == false || isAnythingThere) && !isPlayerInSight)
{
if (movingRight == true)
{
Debug.Log("Поворот");
transform.eulerAngles = new Vector3(0, -180, 0);
movingRight = false;
speed = -speed;
}
else
{
transform.eulerAngles = new Vector3(0, 0, 0);
movingRight = true;
speed = -speed;
}
}
if (isPlayerInSight)
{
state = State.attack;
}
if (enemyIdleCheck == false)
{
StartCoroutine("IfEnemyWantsToIdle");
}
break;
case State.attack:
RaycastHit2D isPlayerThere = Physics2D.Raycast(wallDetection.position, Vector2.right * speed, 3f, playerLayer);
Debug.DrawRay(wallDetection.transform.position, Vector2.right * speed * 3f, Color.red);
if (isPlayerThere)
{
attackDirection = (playerPosition.position - transform.position).normalized;
}
else
{
if (!jumpCooldown)
{
state = State.patrol;
}
}
if (jumpCooldown == false)
{
jumpTimer = Time.time + jumpCooldownInSeconds;
}
break;
case State.idle:
if (isPlayerInSight)
{
state = State.attack;
}
if (!isInIdleState)
{
StartCoroutine("IdlingTime");
}
break;
}
}
IEnumerator IfEnemyWantsToIdle()
{
enemyIdleCheck = true;
Debug.Log("Checking for idle possibility");
yield return new WaitForSeconds(2);
if (Random.Range(0, 20) > 10)
{
state = State.idle;
}
enemyIdleCheck = false;
if (isPlayerInSight)
{
state = State.attack;
enemyIdleCheck = false;
yield break;
}
}
IEnumerator IdlingTime()
{
isInIdleState = true;
while (state == State.idle)
{
yield return new WaitForSeconds(Random.Range(2, 4));
isInIdleState = false;
state = State.patrol;
}
if (isPlayerInSight)
{
isInIdleState = false;
yield break;
}
}
private void FixedUpdate()
{
if (state == State.patrol)
{
if (!enemy.isTakingDamage)
{
rb.velocity = new Vector2(movingSpeed * speed, rb.velocity.y);
}
}
if (state == State.attack)
{
if (!enemy.isTakingDamage)
{
rb.velocity = new Vector2(attackDirection.x * attackSpeed, rb.velocity.y);
}
if ((Random.Range(0, 100) > 90) && !jumpCooldown && onGround)
{
Debug.Log("Прыжок сработал");
//rb.velocity = new Vector2(rb.velocity.x, rb.velocity.y * jumpForce);
rb.AddForce(Vector2.up * jumpForce, ForceMode2D.Impulse);
jumpCooldown = true;
Invoke("JumpCooldownTime", 1f);
}
}
}

Currently you are just not adding further force/velocity. The moment you enter the idle state you should make sure the Rigidbody2D is actually stopped!
IEnumerator IdlingTime()
{
isInIdleState = true;
// actually stop the movement
rb.velocity = Vector2.zero;
// you could even do
rb.isKinematic = true;
while (state == State.idle)
{
yield return new WaitForSeconds(Random.Range(2, 4));
isInIdleState = false;
rb.isKinematic = false;
state = State.patrol;
}
if (isPlayerInSight)
{
isInIdleState = false;
rb.isKinematic = false;
yield break;
}
}
or/and do it in
private void FixedUpdate()
{
switch(state)
{
case State.patrol:
if (!enemy.isTakingDamage)
{
rb.velocity = new Vector2(movingSpeed * speed, rb.velocity.y);
}
break;
case State.attack:
if (!enemy.isTakingDamage)
{
rb.velocity = new Vector2(attackDirection.x * attackSpeed, rb.velocity.y);
}
if ((Random.Range(0, 100) > 90) && !jumpCooldown && onGround)
{
Debug.Log("Прыжок сработал");
//rb.velocity = new Vector2(rb.velocity.x, rb.velocity.y * jumpForce);
rb.AddForce(Vector2.up * jumpForce, ForceMode2D.Impulse);
jumpCooldown = true;
Invoke("JumpCooldownTime", 1f);
}
break;
case State.idle
rb.velocity = Vector2.zero;
break;
}
}

Related

checking if grounded without using oncollision enter/exit?

so I have a script that rotates a cube (by 90 degrees when a direction is pressed) currently im using the oncollision enter to detect walls and when I try to use it to also check if grounded then it will just completely stop everything when i leave one collision and enter another, or it won't fully check when im in mid air and will allow me to move when i don't want to be able to. Any and all help is greatly appreciated.
{
bool isGrounded = true;
private Rigidbody2D rb;
bool leftInput = true;
bool rightInput = true;
public float RollingDuration = 0.2f;
// Start is called before the first frame update
void Start()
{
rb = GetComponent<Rigidbody2D>();
}
// fixed update is for physics
void FixedUpdate()
{
var dir = Vector3.zero;
if (Input.GetKey(KeyCode.LeftArrow) && leftInput && isGrounded)
{
dir = Vector3.left;
}
if (Input.GetKey(KeyCode.RightArrow) && rightInput && isGrounded)
{
dir = Vector3.right;
}
if (dir !=Vector3.zero && !isRolling)
{
StartCoroutine(Roll(dir));
}
}
private void OnCollisionEnter2D(Collision2D collision)
{
//check to see if our player is grounded
if (collision.gameObject.tag == "Grounded")
{
isGrounded = true;
}
if (collision.gameObject.tag == "LeftWall" || collision.gameObject.tag == "RightWall")
{
StopCoroutine("Roll");
if (collision.gameObject.tag == "LeftWall")
{
leftInput = false;
// we are grounded when touching walls
isGrounded = true;
}
if (collision.gameObject.tag == "RightWall")
{
rightInput = false;
// we are grounded when touching walls
isGrounded = true;
}
if (collision.gameObject.tag == null)
{
isGrounded = false;
}
else
{
isRolling = false;
rb.velocity = Vector2.zero;
rb.velocity = new Vector2(0.0f, 0.0f);
rb.angularVelocity = 0.0f;
rb.transform.rotation = Quaternion.Euler(0.0f, 0.0f, 0.0f);
rb.rotation = 0.0f;
}
}
}
bool isRolling = false;
IEnumerator Roll(Vector3 direction)
{
if (direction == Vector3.right && isGrounded)
{
leftInput = true;
}
else if (direction == Vector3.left && isGrounded)
{
rightInput = true;
}
isRolling = true;
var rotAxis = Vector3.Cross(Vector3.up, direction);
var pivot = (rb.transform.position + Vector3.down * 0.5f) + direction * 0.5f;
var startRotation = rb.transform.rotation;
var endRotation = Quaternion.AngleAxis(90.0f, rotAxis) * startRotation;
var startPosition = rb.transform.position;
var endPosition = rb.transform.position + direction;
var rotSpeed = 90.0f / RollingDuration;
var t = 0.0f;
while (t < RollingDuration && isGrounded)
{
t += Time.deltaTime;
if (t < RollingDuration && isGrounded)
{
rb.transform.RotateAround(pivot, rotAxis, rotSpeed * Time.deltaTime);
yield return null;
}
else
{
rb.transform.rotation = endRotation;
rb.transform.position = endPosition;
}
}
isRolling = false;
}
}
I think the most simple and common way to do ground checks is with casting a ray. So just cast a ray into the direction you want to check or try Overlap functions.
Example:
if(Physics.OverlapCircle(point, radius, layerMask)) {
//do stuff
}
So just cast a ray in all direction you want to check or add a overlap function to each side of the cube.

Why does my script make my "dash" have a seemingly random duration and how can I fix it?

I am new to coding. I've been trying to Frankenstein basic tutorials into something of my own and it seems ive finally hit a wall. I'm really not sure what is causing this and would like some help to weed out the problem.
at the moment when I press the dash button (left shift) my character dashes in the direction he is facing but for a random duration. I would like it to be consistent and working properly.
Thanks in advance!
PS: Sorry for the long script, it contains everything to do with player movment.
using System.Collections;
using System.Collections.Generic;
using System.Security.Cryptography;
using UnityEngine;
public class CharacterController : MonoBehaviour
{
//Player Movement
public float speed;
public float jumpForce;
public Transform feetPos;
public float checkRadius;
public LayerMask whatIsGround;
public float dashSpeed;
public float startDashTime;
public float dashCooldownTime = 2;
private float nextFireTime = 0;
public Animator animator;
private Rigidbody2D rb;
private float moveInput;
private bool isGrounded;
private float jumpTimeCounter;
public float jumpTime;
private bool isJumping;
private float dashTime;
public int direction;
void Start()
{
animator.GetComponent<Animator>();
rb = GetComponent<Rigidbody2D>();
dashTime = startDashTime;
}
void FixedUpdate()
{
moveInput = Input.GetAxisRaw("Horizontal");
if (direction < 1 )
rb.velocity = new Vector2(moveInput * speed, rb.velocity.y);
}
void Update()
{
// Moving
isGrounded = Physics2D.OverlapCircle(feetPos.position, checkRadius, whatIsGround);
if (moveInput > 0)
{
transform.eulerAngles = new Vector3(0, 0, 0);
animator.SetBool("Moving", true);
}
else if (moveInput < 0)
{
transform.eulerAngles = new Vector3(0, 180, 0);
animator.SetBool("Moving", true);
}
else
{
animator.SetBool("Moving", false);
}
// Jumping
if (isGrounded == true && Input.GetKeyDown(KeyCode.Space))
{
animator.SetTrigger("IsJumping");
isJumping = true;
jumpTimeCounter = jumpTime;
rb.velocity = Vector2.up * jumpForce;
}
if (Input.GetKey(KeyCode.Space) && isJumping == true)
{
if (jumpTimeCounter > 0)
{
rb.velocity = Vector2.up * jumpForce;
jumpTimeCounter -= Time.deltaTime;
}
else
{
isJumping = false;
}
}
if (Input.GetKeyUp(KeyCode.Space))
{
isJumping = false;
}
if (isGrounded == false)
{
animator.SetBool("Grounded", false);
}
if (isGrounded == true)
{
animator.SetBool("Grounded", true);
}
// Dashing
if (Time.time > nextFireTime)
{
if (direction == 0)
{
if (Input.GetKeyDown(KeyCode.LeftShift))
{
UnityEngine.Debug.Log("beaners");
nextFireTime = Time.time + dashCooldownTime;
if ((transform.rotation.eulerAngles.y == 180))
{
Dashleft();
}
else
{
DashRight();
}
}
}
}
else
{
if(dashTime <= 0)
{
direction = 0;
dashTime = startDashTime;
}
else
{
dashTime -= Time.deltaTime;
}
}
}
void Dashleft()
{
direction = 1;
rb.velocity = Vector2.left * dashSpeed;
}
void DashRight()
{
direction = 1;
rb.velocity = Vector2.right * dashSpeed;
}
}
Random duration is because of the use of Rigidbody2D.
See in Unity Rigidbody2D is responsible for each and every single physical interaction. It mean forces from player like player movement and forces from your environment like friction and collision.
Here what is happening is that when your player is dashing there is also player movement force, which is also applied on your player's Rigidbody2d. And friction of ground on which your player is running/dashing on.
I've added a comment on parts that I've changed.
Updated part of your script:
private bool isDashing;
.
.
.
void Update()
{
//Added: putting a Condition to check if you player is not dashing, if it is then
//player won't be able to do anything, As I've scene and done in many games. if you
//don't want this remove it and see what happens, this is not tested so sorry if there
//is something that is not working as intended.
//dashing condition check
if(!isDashing)
{
// Moving
isGrounded = Physics2D.OverlapCircle(feetPos.position, checkRadius, whatIsGround);
if (moveInput > 0)
{
transform.eulerAngles = new Vector3(0, 0, 0);
animator.SetBool("Moving", true);
}
else if (moveInput < 0)
{
transform.eulerAngles = new Vector3(0, 180, 0);
animator.SetBool("Moving", true);
}
else
{
animator.SetBool("Moving", false);
}
// Jumping
if (isGrounded == true && Input.GetKeyDown(KeyCode.Space))
{
animator.SetTrigger("IsJumping");
isJumping = true;
jumpTimeCounter = jumpTime;
//Changed: use Add force method instead of changing the velocity.
rb.AddForce(Vector2.up * jumpForce, ForceMode2D.Impulse);
//rb.velocity = Vector2.up * jumpForce;
}
if (Input.GetKey(KeyCode.Space) && isJumping == true)
{
if (jumpTimeCounter > 0)
{
//Changed: Same this rb.AddForce...
rb.AddForce(Vector2.up * jumpForce, ForceMode2D.Impulse);
//rb.velocity = Vector2.up * jumpForce;
jumpTimeCounter -= Time.deltaTime;
}
else
{
isJumping = false;
}
}
if (Input.GetKeyUp(KeyCode.Space))
{
isJumping = false;
}
if (isGrounded == false)
{
animator.SetBool("Grounded", false);
}
if (isGrounded == true)
{
animator.SetBool("Grounded", true);
}
}
//dashing condition ends
// Dashing
if (Time.time > nextFireTime)
{
//Here your Dash timer ends.
isDashing = false;
if (direction == 0)
{
if (Input.GetKeyDown(KeyCode.LeftShift))
{
UnityEngine.Debug.Log("beaners");
nextFireTime = Time.time + dashCooldownTime;
//Here your Dash timer Starts.
isDashing = true;
if ((transform.rotation.eulerAngles.y == 180))
{
Dashleft();
}
else
{
DashRight();
}
}
}
}
else
{
if(dashTime <= 0)
{
direction = 0;
dashTime = startDashTime;
}
else
{
dashTime -= Time.deltaTime;
}
}
}
visit Unity - Scripting API: Rigidbody2D.AddForce hope it helps.
Happy Coding

How do I fix my 2D enemy character from sliding instead of stopping when it gives a warning when a character is near to it's range

In game overview
I am still new to C#, and I wanted to know how to fix this problem. The enemy skeleton seems to slide when it reaches the range of the character. I tried finding the solution but failed to do so.
------------------------------ENEMY SCRIPT--------------------------------
private Rigidbody2D myBody;
[Header("Movement")]
public float moveSpeed;
private float minX, maxX;
public float distance;
public int direction;
private bool patrol, detect;
private Transform playerPos;
private Animator anim;
[Header("Attack")]
public Transform attackPos;
public float attackRange;
public LayerMask playerLayer;
public int damage;
AWAKE
void Awake()
{
anim = GetComponent<Animator>();
playerPos = GameObject.Find("George").transform;
myBody = GetComponent<Rigidbody2D>();
}
VOID START
private void Start()
{
maxX = transform.position.x + (distance);
minX = maxX - distance;
//if (Random.value > 0.5) direction = 1;
//else direction = -1;
}
UPDATE
void Update()
{
if (Vector3.Distance(transform.position, playerPos.position) <= 4.0f) patrol = false;
else patrol = true;
}
FIXED UPDATE
private void FixedUpdate()
{
if (anim.GetBool("Death"))
{
myBody.velocity = Vector2.zero;
GetComponent<Collider2D>().enabled = false;
myBody.isKinematic = true;
anim.SetBool("Attack", false);
return;
}
if (myBody.velocity.x > 0)
{
transform.localScale = new Vector2(1f, transform.localScale.y);
anim.SetBool("Attack", false);
}
else if
(myBody.velocity.x < 0) transform.localScale = new Vector2(-1f, transform.localScale.y);
if (patrol)
{
detect = false;
switch (direction)
{
case -1:
if (transform.position.x > minX)
myBody.velocity = new Vector2(-moveSpeed, myBody.velocity.y);
else
direction = 1;
break;
case 1:
if (transform.position.x < maxX)
myBody.velocity = new Vector2(moveSpeed, myBody.velocity.y);
else
direction = -1;
break;
}
}
else
{
if (Vector2.Distance(playerPos.position, transform.position) >= 1.0f)
{
if (!detect)
{
detect = true;
anim.SetTrigger("Detect");
myBody.velocity = new Vector2(0, myBody.velocity.y);
}
if (anim.GetCurrentAnimatorStateInfo(0).IsName("detect")) return;
Vector3 playerDir = (playerPos.position - transform.position).normalized;
if (playerDir.x > 0)
myBody.velocity = new Vector2(moveSpeed + 0.4f, myBody.velocity.y);
else
myBody.velocity = new Vector2(-(moveSpeed + 0.4f), myBody.velocity.y);
}
else if (Vector2.Distance(playerPos.position, transform.position) <= 1.0f)
{
myBody.velocity = new Vector2(0, myBody.velocity.y);
anim.SetBool("Attack", true);
}
}
}

Swipe Controls for Unity runner game

I'm making a running game on android using C#. I try to do swipe control for Unity runner but code does not working properly. Sometimes when I swipe left player goes right and jumping is awful. Here is my code, I do not understand where is my mistake. sometimes it missing touches at all. Player psition is: (10, 1, 0) and the Ground (plane) position is: (10, 0, 0). Player is a simple Cylinder whith Rigidbody.
public int leftLine = 7;
public int rightLine = 13;
public int currentLine = 10;
public int distanceBetweenLines = 3;
public float xSideMoveSpeed = 50f;
public float minSwipDelta = 10f;
public float jumpSpeed = 100f;
Vector2 swipeDelta;
bool canSwipe,
RightSwipe,
LeftSwipe,
UpSwipe,
DownSwipe;
Rigidbody rb;
public float maxDistanceForJumping = 1.05f;
void Start()
{
rb = gameObject.GetComponent<Rigidbody>();
}
void Update()
{
TouchDetector();
MoveByTouch();
}
void FixedUpdate()
{
if (IsGrounded() && UpSwipe)
{
rb.AddForce(Vector3.up * jumpSpeed);
UpSwipe = false;
}
}
public bool IsGrounded()
{
return Physics.Raycast(transform.position, Vector3.down, maxDistanceForJumping);
}
void MoveByTouch()
{
if (canSwipe && RightSwipe)
{
if (currentLine < rightLine)
currentLine += distanceBetweenLines;
canSwipe = false;
swipeDelta = Vector2.zero;
}
if (canSwipe && LeftSwipe)
{
if (currentLine > leftLine)
currentLine -= distanceBetweenLines;
canSwipe = false;
swipeDelta = Vector2.zero;
}
Vector3 newPos = new Vector3(currentLine, transform.position.y, transform.position.z);
transform.position = Vector3.Lerp(transform.position, newPos, xSideMoveSpeed * Time.deltaTime);
}
void TouchDetector()
{
if (Input.touchCount > 0)
{
// can we swipe or ont
if (Input.touches[0].phase == TouchPhase.Began)
{
canSwipe = true;
}
else if (Input.touches[0].phase == TouchPhase.Canceled || Input.touches[0].phase == TouchPhase.Ended)
{
canSwipe = false;
swipeDelta = Vector2.zero;
}
if (Input.touches[0].phase == TouchPhase.Moved)
{
// Calculating delta
if (Mathf.Abs(Input.touches[0].deltaPosition.sqrMagnitude) > minSwipDelta)
swipeDelta = Input.touches[0].deltaPosition;
else
swipeDelta = Vector2.zero;
// Detecting arrows
if (Mathf.Abs(swipeDelta.x) > Mathf.Abs(swipeDelta.y) && swipeDelta.x > 0)
{
RightSwipe = true;
LeftSwipe = UpSwipe = DownSwipe = false;
}
if (Mathf.Abs(swipeDelta.x) > Mathf.Abs(swipeDelta.y) && swipeDelta.x < 0)
{
LeftSwipe = true;
RightSwipe = UpSwipe = DownSwipe = false;
}
if (Mathf.Abs(swipeDelta.x) < Mathf.Abs(swipeDelta.y) && swipeDelta.y > 0)
{
UpSwipe = true;
RightSwipe = LeftSwipe = DownSwipe = false;
}
if (Mathf.Abs(swipeDelta.x) < Mathf.Abs(swipeDelta.y) && swipeDelta.y < 0)
{
DownSwipe = true;
RightSwipe = LeftSwipe = UpSwipe = false;
}
}
}
}

How to do player movement calculations on c# console from unity movement

Question: How do i go about doing a equation on a c# console for where the player should be based on player input from unity.
To explain farther, the client is ran in unity and the server is a c# console application. When the player presses a movement key ex. (w, witch moves the player forward based on local position, as to always make the player move forward) it sends to the server that player pressed w, and then the sever responds and tells the client that it pressed w, changing the player w is pressed bool to true. Then the character moves.
Essentially I am trying to figure out how to make a equation that will do what unity does, but without a transform, or even how the transform works so that i can apply it to the server side.
Here is the client side code:
private void Update()
{
SendKeysToServer();
PlayerController();
PlayerPositionUpdateChecker();
}
public void PlayerController()
{
if (gameObject.name == ntwmng.Playername)
{
MovementControllerPlayer();
JumpControllerPlayer();
RotationControllerPlayer();
MovementFinalizer();
}
else
{
MovementControllerClones();
JumpControllerClones();
RotationControllerClones();
MovementFinalizerClones();
}
}
public void MovementControllerPlayer()
{
if (CharContr.isGrounded)
{
moveDirection = new Vector3(0, 0, 0);
if (wKeyDownPlayer)
{
moveDirection = moveDirection + new Vector3(0, 0, speed * Time.deltaTime);
}
if (sKeyDownPlayer)
{
moveDirection = moveDirection + new Vector3(0, 0, -speed * Time.deltaTime);
}
if (qKeyDownPlayer)
{
moveDirection = moveDirection + new Vector3(-speed * Time.deltaTime, 0, 0);
}
if (eKeyDownPlayer)
{
moveDirection = moveDirection + new Vector3(speed * Time.deltaTime, 0, 0);
}
moveDirection = transform.TransformDirection(moveDirection);
//moveDirection *= speed;
}
}
public void RotationControllerPlayer()
{
if (dKeyDownPlayer)
{
transform.Rotate(0, RotationSpeed * Time.deltaTime, 0);
}
if(aKeyDownPlayer)
{
transform.Rotate(0, -RotationSpeed * Time.deltaTime, 0);
}
}
public void JumpControllerPlayer()
{
if (CharContr.isGrounded)
{
if (SpaceKeyDownPlayer)
{
moveDirection.y = jumpSpeed * Time.deltaTime;
}
}
}
public void MovementFinalizer()
{
moveDirection.y -= gravity * Time.deltaTime;
CharContr.Move(moveDirection);
}
public void CameraAndListenerController()
{
if (gameObject.name == ntwmng.Playername)
{
if (playercam.enabled == false)
{
playercam.enabled = true;
}
if (AudioListener.enabled == false)
{
AudioListener.enabled = true;
}
}
else
{
if (playercam.enabled == true)
{
playercam.enabled = false;
}
if (AudioListener.enabled == true)
{
AudioListener.enabled = false;
}
}
}
public void SendKeysToServer()
{
NetworkStream NtwrkStrm = ServerConnection.GetStream();
IFormatter Formatter = new BinaryFormatter();
foreach (KeyCode kcode in Enum.GetValues(typeof(KeyCode)))
{
if(Input.GetKeyDown(kcode))
{
string type = "Movement Update Key Down";
string kycode = Convert.ToString(kcode);
//Debug.Log(kycode);
Formatter.Serialize(NtwrkStrm, type);
NtwrkStrm.Flush();
Formatter.Serialize(NtwrkStrm, ntwmng.Playername);
NtwrkStrm.Flush();
Formatter.Serialize(NtwrkStrm, kycode);
NtwrkStrm.Flush();
}else
if(Input.GetKeyUp(kcode))
{
string type = "Movement Update Key Up";
string kycode = Convert.ToString(kcode);
//Debug.Log(kycode);
Formatter.Serialize(NtwrkStrm, type);
NtwrkStrm.Flush();
Formatter.Serialize(NtwrkStrm, ntwmng.Playername);
NtwrkStrm.Flush();
Formatter.Serialize(NtwrkStrm, kycode);
NtwrkStrm.Flush();
}
}
}
public void MovementControllerClones()
{
if (CharContr.isGrounded)
{
moveDirection = new Vector3(0, 0, 0);
if (wKeyDownClone)
{
moveDirection = moveDirection + new Vector3(0, 0, speed * Time.deltaTime);
}
if (sKeyDownClone)
{
moveDirection = moveDirection + new Vector3(0, 0, -speed * Time.deltaTime);
}
if (qKeyDownClone)
{
moveDirection = moveDirection + new Vector3(-speed * Time.deltaTime, 0, 0);
}
if (eKeyDownClone)
{
moveDirection = moveDirection + new Vector3(speed * Time.deltaTime, 0, 0);
}
moveDirection = transform.TransformDirection(moveDirection);
//moveDirection *= speed;
}
}
public void RotationControllerClones()
{
if (dKeyDownClone)
{
transform.Rotate(0, RotationSpeed * Time.deltaTime, 0);
}
if (aKeyDownClone)
{
transform.Rotate(0, -RotationSpeed * Time.deltaTime, 0);
}
}
public void JumpControllerClones()
{
if (CharContr.isGrounded)
{
if (SpaceKeyDownClone)
{
moveDirection.y = jumpSpeed* Time.deltaTime;
}
}
}
public void MovementFinalizerClones()
{
moveDirection.y -= gravity * Time.deltaTime;
CharContr.Move(moveDirection);
}
public void CloneKeyUpdater(string type,string kcode)
{
//Debug.Log("Key " + kcode + " Clone Updating");
if (type == "Movement Update Key Down")
{
if (kcode == "W")
{
wKeyDownClone = true;
}
if (kcode == "A")
{
aKeyDownClone = true;
}
if (kcode == "D")
{
dKeyDownClone = true;
}
if (kcode == "S")
{
sKeyDownClone = true;
}
if (kcode == "Q")
{
qKeyDownClone = true;
}
if (kcode == "E")
{
eKeyDownClone = true;
}
if (kcode == "Space")
{
SpaceKeyDownClone = true;
}
}
else if (type == "Movement Update Key Up")
{
if (kcode == "W")
{
wKeyDownClone = false;
}
if (kcode == "A")
{
aKeyDownClone = false;
}
if (kcode == "D")
{
dKeyDownClone = false;
}
if (kcode == "S")
{
sKeyDownClone = false;
}
if (kcode == "Q")
{
qKeyDownClone = false;
}
if (kcode == "E")
{
eKeyDownClone = false;
}
if (kcode == "Space")
{
SpaceKeyDownClone = false;
}
}
}
public void PlayerKeyUpdater(string type, string kcode)
{
//Debug.Log("Key down " + kcode + " Updating");
if (type == "Movement Update Key Down")
{
if (kcode == "W")
{
wKeyDownPlayer = true;
}
if (kcode == "A")
{
aKeyDownPlayer = true;
}
if (kcode == "D")
{
dKeyDownPlayer = true;
}
if (kcode == "S")
{
sKeyDownPlayer = true;
}
if (kcode == "Q")
{
qKeyDownPlayer = true;
}
if (kcode == "E")
{
eKeyDownPlayer = true;
}
if (kcode == "Space")
{
SpaceKeyDownPlayer = true;
}
}
else if (type == "Movement Update Key Up")
{
if (kcode == "W")
{
wKeyDownPlayer = false;
}
if (kcode == "A")
{
aKeyDownPlayer = false;
}
if (kcode == "D")
{
dKeyDownPlayer = false;
}
if (kcode == "S")
{
sKeyDownPlayer = false;
}
if (kcode == "Q")
{
qKeyDownPlayer = false;
}
if (kcode == "E")
{
eKeyDownPlayer = false;
}
if (kcode == "Space")
{
SpaceKeyDownPlayer = false;
}
}
}
Any help will be muchly appreciated. :)
Edit:
so i have figured out a equation that i am using to try and mimic player movement, as of right now it only work between 0 and 90 degrees, just tell i get it exact. the equation comes out really close, but is just a tiny bit off. Any suggestions? Also, this is running on client side, no server influence, so that I can get the math to an exact. The math comes out about 1 unit per second slower then the players current position. Basically after pressing w for 1 second with speed = 20 the math comes out to 19 and actual position is 20.
here is code
if (CharContr.velocity != Vector3.zero)//checks if the player is moving
{
if (rotation < 90f && rotation > 0f) // makes sure the rotation is 0-90
{
percent = (100 / (90 / rotation)) / 100; // gets the percent
x = x + (percent * speed * Time.deltaTime); //adds to current position multiplied by speed and delta time
invertPercent = 1 - percent; //gets the percent for z
z = z + (invertPercent * speed * Time.deltaTime); // adds and stuff again
}
This is really complicated than you thought if you want to implement it yourself instead of using Unity's built-in NetworkTransform. Read this "Client-Side Prediction and Server Reconciliation" article. There are many parts of that article but it shows you what's going on and how this is done.
Although, Unity simplified a part of this if you are using Rigidbody by providing a new function (Physics.Simulate). You simulate all the Rigidbody on the server with the Physics.Simulate function, serialize the transform of each one and send to all the clients.
On the clients, receive the data, de-serialize them then lerp from the current transform to the received ones. You can find an example of how to use Physics.Simulate to determine the position of a Rigidbody in x second here.
Sending keycode to server and syncronize position based on bool is not best practice.
The good practice would be, sending 3 float value of x, y, and z position to the server, then broadcast it to other player.
so other player has the exact position without approximation
Sorry if i answer in wrong place, because i don't have enough rep to make comment.
so i did some searching and have come up with a solution, this is only for if the player is moving forward and the player direction is between 0 and 90. basically i have to use transform.translate instead of using a character controller. the reason i am doing this is so that when the player presses w it will send it to the server and the server can run this at the same time, then use the info to be able to tell were players should be.
if (rotation < 90f && rotation > 0f)
{
moveDirection = new Vector3(0, 0, 0);
percent = (100 / (90 / rotation)) / 100;
invertPercent = 1 - percent;
x = percent * speed;
z = invertPercent * speed;
transform.Translate(x * Time.deltaTime, 0, z * Time.deltaTime, Space.World);
newposition = newposition + new Vector3(x * Time.deltaTime, 0, z * Time.deltaTime);
}

Categories

Resources