Double jump not working as expected - c#

that's my code to handle double jump.But sometimes it doesn't work.
First time I touch the screen my character jumps up ( variable doublejump = true ) . When I touch the screen a second time my character jumps higher(double jump = false)(double jump worked).
But sometimes when I touch the screen for the first time(no need to touch the screen a second time) doublejump variable = false(double jump not working as I expected)
Help me fix that
My code:
void FixedUpdate ()
{
isGrounded = GroundedCheck ();
if (gm.gameState == GameManager.GameState.playing) {
foreach (GameObject g in gm.deadObjects) {
if (g.name == "P13") {
g.GetComponent<Mygroup> ().targetName = "P12";
} else if (g.name == "P12") {
g.GetComponent<Mygroup> ().targetName = "P11";
} else if (g.name == "P11") {
g.GetComponent<Mygroup> ().targetName = "P10";
} else if (g.name == "P10") {
g.GetComponent<Mygroup> ().targetName = "P9";
} else if (g.name == "P9") {
g.GetComponent<Mygroup> ().targetName = "P8";
} else if (g.name == "P8") {
g.GetComponent<Mygroup> ().targetName = "P7";
} else if (g.name == "P7") {
g.GetComponent<Mygroup> ().targetName = "P6";
} else if (g.name == "P6") {
g.GetComponent<Mygroup> ().targetName = "P5";
} else if (g.name == "P5") {
g.GetComponent<Mygroup> ().targetName = "P4";
} else if (g.name == "P4") {
g.GetComponent<Mygroup> ().targetName = "P3";
} else if (g.name == "P3") {
g.GetComponent<Mygroup> ().targetName = "P2";
} else if (g.name == "P2") {
g.GetComponent<Mygroup> ().targetName = "P1";
} else if (g.name == "P1") {
g.GetComponent<Mygroup> ().targetName = "P0";
} else if (g.name == "P0") {
g.GetComponent<Mygroup> ().targetName = null;
}
}
if (this.gameObject.name == "P0") {
targetName = "";
} else if (this.gameObject.name == "P1")
targetName = "P0";
else if (this.gameObject.name == "P2")
targetName = "P1";
else if (this.gameObject.name == "P3")
targetName = "P2";
else if (this.gameObject.name == "P4")
targetName = "P3";
else if (this.gameObject.name == "P5")
targetName = "P4";
else if (this.gameObject.name == "P6")
targetName = "P5";
else if (this.gameObject.name == "P7")
targetName = "P6";
else if (this.gameObject.name == "P8")
targetName = "P7";
else if (this.gameObject.name == "P9")
targetName = "P8";
else if (this.gameObject.name == "P10")
targetName = "P9";
else if (this.gameObject.name == "P11")
targetName = "P10";
else if (this.gameObject.name == "P12")
targetName = "P11";
target = GameObject.Find (targetName);
if (isGrounded) {
jumping = false;
doubleJump = false;
jumpAnim = false;
if (this.gameObject.name == "P0" && isGrounded && !doubleJump && !jumping) {
if (Input.GetMouseButtonDown (0) && this.gameObject.name == "P0") {
jumping = true;
rid.velocity = new Vector3 (0, 50f * jump, 0);
doubleJump = true;
}
}
if (this.gameObject.name == "P0" && !isGrounded && doubleJump && jumping) {
if (Input.GetMouseButtonDown (0) && this.gameObject.name == "P0") {
rid.velocity = new Vector3 (0, 60f * jump, 0);
doubleJump = false;
}
}
if (target != null && this.gameObject.name != "P0" && isGrounded && target.GetComponent<Mygroup> ().doubleJump && !target.GetComponent<Mygroup> ().isGrounded) {
StartCoroutine (Jump ());
}
if (target != null && this.gameObject.name != "P0" && !isGrounded && doubleJump && !target.GetComponent<Mygroup> ().isGrounded && !target.GetComponent<Mygroup> ().doubleJump) {
StartCoroutine (JumpDouble ());
}
}
IEnumerator Jump ()
{
yield return new WaitForSeconds (time);
if (gameObject.name == "P1")
rid.velocity = new Vector3 (0, 49.6f * jump, 0);
if (gameObject.name == "P2")
rid.velocity = new Vector3 (0, 49.4f * jump, 0);
if (gameObject.name == "P3")
rid.velocity = new Vector3 (0, 49.2f * jump, 0);
if (gameObject.name == "P4")
rid.velocity = new Vector3 (0, 49f * jump, 0);
if (gameObject.name == "P5")
rid.velocity = new Vector3 (0, 48.8f * jump, 0);
if (gameObject.name == "P6")
rid.velocity = new Vector3 (0, 48.6f * jump, 0);
if (gameObject.name == "P7")
rid.velocity = new Vector3 (0, 48.4f * jump, 0);
if (gameObject.name == "P8")
rid.velocity = new Vector3 (0, 48.2f * jump, 0);
if (gameObject.name == "P9")
rid.velocity = new Vector3 (0, 48f * jump, 0);
if (gameObject.name == "P10")
rid.velocity = new Vector3 (0, 47.8f * jump, 0);
if (gameObject.name == "P11")
rid.velocity = new Vector3 (0, 47.6f * jump, 0);
if (gameObject.name == "P12")
rid.velocity = new Vector3 (0, 47.4f * jump, 0);
jumping = true;
doubleJump = true;
}
IEnumerator JumpDouble ()
{
yield return new WaitForSeconds (time);
if (doubleJump) {
if (gameObject.name == "P1")
rid.velocity = new Vector3 (0, 59.8f * jump, 0);
if (gameObject.name == "P2")
rid.velocity = new Vector3 (0, 59.6f * jump, 0);
if (gameObject.name == "P3")
rid.velocity = new Vector3 (0, 59.4f * jump, 0);
if (gameObject.name == "P4")
rid.velocity = new Vector3 (0, 59.2f * jump, 0);
if (gameObject.name == "P5")
rid.velocity = new Vector3 (0, 59f * jump, 0);
if (gameObject.name == "P6")
rid.velocity = new Vector3 (0, 58.8f * jump, 0);
if (gameObject.name == "P7")
rid.velocity = new Vector3 (0, 58.6f * jump, 0);
if (gameObject.name == "P8")
rid.velocity = new Vector3 (0, 58.4f * jump, 0);
if (gameObject.name == "P9")
rid.velocity = new Vector3 (0, 58.2f * jump, 0);
if (gameObject.name == "P10")
rid.velocity = new Vector3 (0, 58f * jump, 0);
if (gameObject.name == "P11")
rid.velocity = new Vector3 (0, 57.8f * jump, 0);
if (gameObject.name == "P12")
rid.velocity = new Vector3 (0, 57.6f * jump, 0);
doubleJump = false;
jumping = false;
}
}

I think there is no need to use two variables 'doubleJump & jumping'
Might this work, check following one
if (this.gameObject.name == "P0" && isGrounded && !jumping) {
if (Input.GetMouseButtonDown (0)) {
jumping = true;
rid.velocity = new Vector3 (0, 50f * jump, 0);
}
}
if (this.gameObject.name == "P0" && !isGrounded && jumping) {
if (Input.GetMouseButtonDown (0)) {
rid.velocity = new Vector3 (0, 60f * jump, 0);
jumping = false;
}
}

if (this.gameObject.name == "P0" && !isGrounded && doubleJump && jumping) {
if (Input.GetMouseButtonDown (0) && this.gameObject.name == "P0") {
rid.velocity = new Vector3 (0, 60f * jump, 0);
doubleJump = false;
My suggestion is that you remove '&& jumping' from your if statement.
Hope it helps.
Cheers.

Related

Make pacman move randomly

I am creating a pacman game using noobtuts' tutorial. https://noobtuts.com/unity/2d-pacman-game However I want to make pacman to be able move on its own. My idea is to make it choose a random direction to move, and it will head into that direction if it is a valid move. How should I do it? Appreciate any answers!
This is noobtuts' code that moves pacman with user input.
Vector2 dest = Vector2.zero;
void Start()
{
dest = transform.position;
disabled = false;
}
void FixedUpdate()
{
// Move closer to Destination
Vector2 p = Vector2.MoveTowards(transform.position, dest, speed);
GetComponent<Rigidbody2D>().MovePosition(p);
// Check for Input if not moving
if ((Vector2)transform.position == dest && !disabled)
{
if (DirectionEmulator.direction == "up" && valid(Vector2.up))
dest = (Vector2)transform.position + Vector2.up;
if (DirectionEmulator.direction == "right" && valid(Vector2.right))
dest = (Vector2)transform.position + Vector2.right;
if (DirectionEmulator.direction == "down" && valid(-Vector2.up))
dest = (Vector2)transform.position - Vector2.up;
if (DirectionEmulator.direction == "left" && valid(-Vector2.right))
dest = (Vector2)transform.position - Vector2.right;
}
// Animation Parameters
Vector2 dir = dest - (Vector2)transform.position;
GetComponent<Animator>().SetFloat("DirX", dir.x);
GetComponent<Animator>().SetFloat("DirY", dir.y);
}
bool valid(Vector2 dir)
{
// Cast Line from 'next to Pac-Man' to 'Pac-Man'
Vector2 pos = transform.position;
RaycastHit2D hit = Physics2D.Linecast(pos + dir, pos);
return (hit.collider == GetComponent<Collider2D>());
}
I managed to make it work as of now, but I believe much more can be improved. Please provide any input if you have any solutions!
private string move;
Vector2 dest = Vector2.zero;
void Start()
{
dest = transform.position;
disabled = false;
move = "right";
}
void FixedUpdate() //use this to decide movement
{
// Move closer to Destination
Vector2 p = Vector2.MoveTowards(transform.position, dest, speed);
GetComponent<Rigidbody2D>().MovePosition(p);
// determine next destination
if ((Vector2)transform.position == dest && !disabled)
{
//check valid direction
if (move == "up" && valid(Vector2.up))
{
dest = (Vector2)transform.position + Vector2.up;
}
if (move == "right" && valid(Vector2.right))
{
dest = (Vector2)transform.position + Vector2.right;
}
if (move == "down" && valid(-Vector2.up))
{
dest = (Vector2)transform.position - Vector2.up;
}
if (move == "left" && valid(-Vector2.right))
{
dest = (Vector2)transform.position - Vector2.right;
}
//if not valid, change direction
// choose random valid direction
System.Random rnd = new System.Random();
int rand = rnd.Next(1, 4);
if (rand == 1 && valid(Vector2.up))
{
move = "up";
}
else if (rand == 2 && valid(Vector2.right))
{
move = "right";
}
else if (rand == 3 && valid(-Vector2.up))
{
move = "down";
}
else if (rand == 4 && valid(-Vector2.right))
{
move = "left";
}
}
// Animation Parameters
Vector2 dir = dest - (Vector2)transform.position;
GetComponent<Animator>().SetFloat("DirX", dir.x);
GetComponent<Animator>().SetFloat("DirY", dir.y);
}
bool valid(Vector2 dir)
{
// Cast Line from 'next to Pac-Man' to 'Pac-Man'
Vector2 pos = transform.position;
RaycastHit2D hit = Physics2D.Linecast(pos + dir, pos);
return (hit.collider == GetComponent<Collider2D>());
}

Function fires in wrong switch case

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;
}
}

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.

Assistance with unity 2d melee attack

I'm making a 2D platform fighter but I've looked all over the internet and I'm not sure i can find what I'm looking for. I'm trying to make a melee attack to when you hit R-click on the mouse it dashes in the direction you are walking.
Ill try and figure out knock-back or dmg later. Any help with the movement of the script?
I'll list my current movement code below.
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
namespace NinjaController {
[RequireComponent(typeof(Rigidbody2D))]
[RequireComponent(typeof(Collider2D))]
public class NinjaController : MonoBehaviour {
private Rigidbody2D RBody { get; set; }
[SerializeField]
private PhysicsParams physicsParams;
public Vector2 Velocity { get { return(RBody.velocity); } }
public Vector2 VelocityRelativeGround { get { return(Velocity / PhysicsParams.onGroundMaxVelHorizontal); } }
private float timeRealLastGroundCollision = 0;
private float timeRealLastWallLeftCollision = 0;
private float timeRealLastWallRightCollision = 0;
public bool IsOnGround {
get {
return GetIsColliding(timeRealLastGroundCollision);
}
}
public bool IsOnWallLeft {
get {
return GetIsColliding(timeRealLastWallLeftCollision);
}
}
public bool IsOnWallRight {
get {
return GetIsColliding(timeRealLastWallRightCollision);
}
}
public bool IsInAir { get { return isPlayerInAir; } }
private bool GetIsColliding(float timeLastCollision) {
return(Time.realtimeSinceStartup < timeLastCollision + 0.05f);
}
private Vector2 currentVelocity = Vector2.zero;
private Vector2 currentForce = Vector2.zero;
private float EntityMass { get { return(PhysicsParams.playerMass); } }
private bool isPlayerInAir = false;
private bool keyJumpRetrigger = false;
private bool keyJumpPressed = false;
private bool isPlayerOnWall = false;
public PhysicsParams PhysicsParams {
get { return physicsParams; }
set { physicsParams = value; }
}
public Vector2 CurrentForce { get { return currentForce; } }
public bool IsOnWall { get { return isPlayerOnWall; } }
private List<Renderer> allRenderers;
public List<Renderer> AllRenderers { get { return allRenderers; } }
public Vector3 Position {
get {
return transform.position;
}
set {
transform.position = value;
}
}
public Vector2 Position2D {
get {
return transform.position;
}
set {
transform.position = value;
}
}
public void Awake() {
RBody = GetComponent<Rigidbody2D>();
allRenderers = new List<Renderer>(GetComponentsInChildren<Renderer>(true));
}
public void Update() {
//let's reset forces to 0 and then add regular gravitation
SimResetForce();
SimAddForce(new Vector2(0, PhysicsParams.gameGravity) * EntityMass);
//process key input (like jumping key pressed, etc...)
ProcessInput();
//simulate position and velocity based on all acting forces
ComputeVelocity(Time.deltaTime);
//collision detection with static world
isPlayerOnWall = IsOnWallLeft || IsOnWallRight;
isPlayerInAir = IsOnGround == false;
}
private void SimResetForce() {
currentForce = Vector2.zero;
}
private void SimAddForce(Vector2 force) {
currentForce += force;
}
private void ComputeVelocity(float dt) {
currentVelocity += (currentForce / EntityMass) * dt;
//let's cap the speed in case its higher than the max
if (isPlayerInAir) {
currentVelocity.x = Mathf.Clamp(currentVelocity.x, -PhysicsParams.inAirMaxVelHorizontal, PhysicsParams.inAirMaxVelHorizontal);
} else {
currentVelocity.x = Mathf.Clamp(currentVelocity.x, -PhysicsParams.onGroundMaxVelHorizontal, PhysicsParams.onGroundMaxVelHorizontal);
}
RBody.velocity = currentVelocity;
}
private void ProcessInput() {
bool isKeyDownJump = Input.GetButton("Jump");
float inputAxisX = Input.GetAxisRaw("Horizontal");
bool isKeyDownLeft = inputAxisX < -0.5f;
bool isKeyDownRight = inputAxisX > 0.5f;
//-----------------
//JUMPING LOGIC:
//player is on ground
if (isPlayerInAir == false) {
//in case the player is on ground and does not press the jump key, he
//should be allowed to jump
if (isKeyDownJump == false) {
keyJumpRetrigger = true;
}
//did player press down the jump button?
if (isKeyDownJump == true && keyJumpRetrigger == true) {
keyJumpPressed = true;
keyJumpRetrigger = false;
//when pressing jump on ground we set the upwards velocity directly
currentVelocity = new Vector2(currentVelocity.x, PhysicsParams.jumpUpVel);
}
} else if (isPlayerOnWall == true) {
//let's allow jumping again in case of being on the wall
if (isKeyDownJump == false) {
keyJumpRetrigger = true;
}
if (currentVelocity.y < 0) {//apply friction when moving downwards
SimAddForce(new Vector2(0, PhysicsParams.wallFriction) * EntityMass);
}
if (currentVelocity.y < PhysicsParams.wallFrictionStrongVelThreshold) {//apply even more friction when moving downwards fast
SimAddForce(new Vector2(0, PhysicsParams.wallFrictionStrong) * EntityMass);
}
if (isKeyDownJump == true && keyJumpRetrigger == true) {
keyJumpPressed = true;
keyJumpRetrigger = false;
//in case we are moving down -> let's set the velocity directly
//in case we are moving up -> sum up velocity
if (IsOnWallLeft == true) {
if (currentVelocity.y <= 0) {
currentVelocity = new Vector2(PhysicsParams.jumpWallVelHorizontal, PhysicsParams.jumpWallVelVertical);
} else {
currentVelocity = new Vector2(PhysicsParams.jumpWallVelHorizontal, currentVelocity.y + PhysicsParams.jumpWallVelVertical);
}
} else if (IsOnWallRight == true) {
if (currentVelocity.y <= 0)
currentVelocity = new Vector2(-PhysicsParams.jumpWallVelHorizontal, PhysicsParams.jumpWallVelVertical);
else
currentVelocity = new Vector2(-PhysicsParams.jumpWallVelHorizontal, currentVelocity.y + PhysicsParams.jumpWallVelVertical);
}
}
}
//did player lift the jump button?
if (isKeyDownJump == false) {
keyJumpPressed = false;
}
//let's apply force in case we are holding the jump key during a jump.
if (keyJumpPressed == true) {
SimAddForce(new Vector2(0, PhysicsParams.jumpUpForce) * EntityMass);
}
//however let's stop doing that as soon as we fall down after the up-phase.
if (keyJumpPressed == true && currentVelocity.y <= 0) {
keyJumpPressed = false;
}
//let's apply additional gravity in case we're in air moving up but not holding the jump button
if (keyJumpPressed == false && isPlayerInAir == true && currentVelocity.y > 0) {
SimAddForce(new Vector2(0, PhysicsParams.jumpGravity) * EntityMass);
}
//-----------------
//IN AIR SIDEWAYS:
if (isPlayerInAir == true) {
//steering into moving direction (slow accel)
if (isKeyDownLeft == true && currentVelocity.x <= 0)
SimAddForce(new Vector2(-PhysicsParams.inAirMoveHorizontalForce, 0) * EntityMass);
else if (isKeyDownRight == true && currentVelocity.x >= 0)
SimAddForce(new Vector2(PhysicsParams.inAirMoveHorizontalForce, 0) * EntityMass);
//steering against moving direction (fast reverse accel)
else if (isKeyDownLeft == true && currentVelocity.x >= 0)
SimAddForce(new Vector2(-PhysicsParams.inAirMoveHorizontalForceReverse, 0) * EntityMass);
else if (isKeyDownRight == true && currentVelocity.x <= 0)
SimAddForce(new Vector2(PhysicsParams.inAirMoveHorizontalForceReverse, 0) * EntityMass);
}
//-----------------
//ON GROUND SIDEWAYS:
if (isPlayerInAir == false) {
//steering into moving direction (slow accel)
if (isKeyDownLeft == true && currentVelocity.x <= 0)
SimAddForce(new Vector2(-PhysicsParams.onGroundMoveHorizontalForce, 0) * EntityMass);
else if (isKeyDownRight == true && currentVelocity.x >= 0)
SimAddForce(new Vector2(PhysicsParams.onGroundMoveHorizontalForce, 0) * EntityMass);
//steering against moving direction (fast reverse accel)
else if (isKeyDownLeft == true && currentVelocity.x >= 0)
SimAddForce(new Vector2(-PhysicsParams.onGroundMoveHorizontalForceReverse, 0) * EntityMass);
else if (isKeyDownRight == true && currentVelocity.x <= 0)
SimAddForce(new Vector2(PhysicsParams.onGroundMoveHorizontalForceReverse, 0) * EntityMass);
//not steering -> brake due to friction.
else if (isKeyDownLeft != true && isKeyDownRight != true && currentVelocity.x > 0)
SimAddForce(new Vector2(-PhysicsParams.groundFriction, 0) * EntityMass);
else if (isKeyDownLeft != true && isKeyDownRight != true && currentVelocity.x < 0)
SimAddForce(new Vector2(PhysicsParams.groundFriction, 0) * EntityMass);
//in case the velocity is close to 0 and no keys are pressed we should make the the player stop.
//to do this let's first undo the prior friction force, and then set the velocity to 0.
if (isKeyDownLeft != true && isKeyDownRight != true && currentVelocity.x > 0 && currentVelocity.x < PhysicsParams.groundFrictionEpsilon) {
SimAddForce(new Vector2(PhysicsParams.groundFriction, 0) * EntityMass);
currentVelocity.x = 0;
} else if (isKeyDownLeft != true && isKeyDownRight != true && currentVelocity.x < 0 && currentVelocity.x > -PhysicsParams.groundFrictionEpsilon) {
SimAddForce(new Vector2(-PhysicsParams.groundFriction, 0) * EntityMass);
currentVelocity.x = 0;
}
}
}
public void ResetVelocity() {
currentVelocity = Vector2.zero;
}
public void OnCollisionStay2D(Collision2D collision) {
foreach (ContactPoint2D contactPoint in collision.contacts) {
if (GetIsVectorClose(new Vector2(0, 1), contactPoint.normal)) {
timeRealLastGroundCollision = Time.realtimeSinceStartup;
currentVelocity.y = Mathf.Clamp(currentVelocity.y, 0, Mathf.Abs(currentVelocity.y));
}
if (GetIsVectorClose(new Vector2(1, 0), contactPoint.normal)) {
timeRealLastWallLeftCollision = Time.realtimeSinceStartup;
currentVelocity.x = Mathf.Clamp(currentVelocity.x, 0, Mathf.Abs(currentVelocity.x));
}
if (GetIsVectorClose(new Vector2(-1, 0), contactPoint.normal)) {
timeRealLastWallRightCollision = Time.realtimeSinceStartup;
currentVelocity.x = Mathf.Clamp(currentVelocity.x, -Mathf.Abs(currentVelocity.x), 0);
}
if(GetIsVectorClose(Vector2.down, contactPoint.normal)) {
currentVelocity.y = Mathf.Clamp(currentVelocity.y, -Mathf.Abs(currentVelocity.y), 0);
}
}
}
private bool GetIsVectorClose(Vector2 vectorA, Vector2 vectorB) {
return(Mathf.Approximately(0, Vector2.Distance(vectorA, vectorB)));
}
public void OnLifeChanged (int life, Vector2 contactVector) {
const float forceEnemyCollision = 15.0f;
currentVelocity = contactVector.normalized * forceEnemyCollision;
}
public void ResetPlayer() {
currentVelocity = Vector2.zero;
}
}
}
For dashing, it will be something along the line of:
bool isDashing;
float currentDashTime = 0; // How long in seconds since the dash started.
float dashTime = 1f; // How long in seconds will the dash be.
float dashSpeed = 10f;
private void Update()
{
if (Input.GetMouseButtonDown(1)) // Right click
{
if (!isDashing) StartCoroutine(Dash());
}
}
private IEnumerator Dash()
{
isDashing = true;
currentDashTime = 0;
Vector2 facingDirection = new Vector2(transform.right.x, transform.right.y)
rb2d.AddForce(facingDirection * dashSpeed);
while (currentDashTime < dashTime)
{
currentDashTime += Time.deltaTime;
yield return null;
}
// If you want the character to stop after dashing ends.
// rb.velocity = Vector2.zero;
isDashing = false;
}
As for melee attacks, I'll recommend looking into 2D Raycasts, provided your enemies have colliders on them. You can raycast before you start dashing so you know what you will collide with during the dash beforehand.
RaycastHit2D hit = Physics2D.Raycast(transform.position, facingDirection);
if (hit.collider != null)
{
// Check for enemy, damage the enemy... etc.
}
Use Physics2D.RaycastAll if you want to get all enemies hit along a line. Physics2D.RayCast only returns the first collider hit.

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