I was coding movement code for my game using this video: Movement code video.
Pardon my garbage code...
void Move(float dir,bool crouchFlag)
{
if(!crouchFlag)
{
if(Physics2D.OverlapCircle(OverheadChecker.position,CelingCirSize,gLayerMask))
{
crouchFlag = true;
}
}
Stand.enabled = !crouchFlag;
Stand2.enabled = !crouchFlag;
Croucher.enabled = crouchFlag;
#region Move & run
if (isGrounded && !crouchFlag && !isOnSlope)
{
Controller.XMove(dir,Speed,rb2d,velPower,acceleration,decceleration);
} else if (isGrounded && isOnSlope && canWalkOnSlope)
{
float TargetSpeed = -dir * Speed;
float TargetSpeedDif = TargetSpeed - rb2d.velocity.x;
float accelerRate = (Mathf.Abs(TargetSpeed) > 0.01f) ? airacceleration : airdecceleration;
float MoveDir = Mathf.Pow(Mathf.Abs(TargetSpeedDif) * accelerRate, velPower) * Mathf.Sign(TargetSpeedDif);
float MoveDirX = MoveDir * slopeNormalPerp.x * MultSlope;
float MoveDirY = MoveDir * slopeNormalPerp.y * MultSlope;
rb2d.AddForce(MoveDirX * Vector2.right);
rb2d.AddForce(MoveDirY * Vector2.up);
}
else if (!isGrounded)
{
float TargetSpeed = dir * Speed;
float TargetSpeedDif = TargetSpeed - rb2d.velocity.x;
float accelerRate = (Mathf.Abs(TargetSpeed) > 0.01f) ? airacceleration : airdecceleration;
float MoveDir = Mathf.Pow(Mathf.Abs(TargetSpeedDif) * accelerRate, velPower) * Mathf.Sign(TargetSpeedDif);
if (rb2d.velocity.y > 0 && !Input.GetButton("Jump"))
{
MoveDir = MoveDir * xJumpForce;
}
rb2d.AddForce(MoveDir * Vector2.right);
}else if (isGrounded && crouchFlag)
{
rb2d.sharedMaterial = noFriction;
float TargetSpeed = dir * CrouchSpeed;
float TargetSpeedDif = TargetSpeed - rb2d.velocity.x;
float accelerRate = (Mathf.Abs(TargetSpeed) > 0.01f) ? acceleration : Crouchdecceleration;
float MoveDir = Mathf.Pow(Mathf.Abs(TargetSpeedDif) * accelerRate, velPower) * Mathf.Sign(TargetSpeedDif);
rb2d.AddForce(MoveDir * Vector2.right);
}
if (isGrounded && Mathf.Abs(HorizontalValue) < 0.01f)
{
float amount = Mathf.Min(Mathf.Abs(rb2d.velocity.x), Mathf.Abs(fricAmount));
amount *= Mathf.Sign(rb2d.velocity.x);
rb2d.AddForce(Vector2.right * -amount, ForceMode2D.Impulse);
}
Vector3 CurrentScale = transform.localScale;
if(Right && dir > 0)
{
transform.localScale = new Vector3(1.4f, 1.4f
, 1);
Right = false;
}
else if (!Right == dir < 0)
{
transform.localScale = new Vector3(-1.4f, 1.4f, 1);
Right = true;
}
#endregion
}
Then I made slopes using a Sprite Shape Controller:
But, the character got stuck on the slopes when going up them, so I used this video for slopes:Fixing slopes video
Irrelevant code is removed:
private void SlopeCheck()
{
checkPos = transform.position - (Vector3)(new Vector2(0.0f, colliderSize.y / 2));
SlopeCheckHorizontal(checkPos);
SlopeCheckVertical(checkPos);
}
private void SlopeCheckHorizontal(Vector2 checkPos)
{
RaycastHit2D slopeHitFront = Physics2D.Raycast(checkPos, transform.right, slopeCheckDistance, gLayerMask);
RaycastHit2D slopeHitBack = Physics2D.Raycast(checkPos, -transform.right, slopeCheckDistance, gLayerMask);
if (slopeHitFront)
{
isOnSlope = true;
slopeSideAngle = Vector2.Angle(slopeHitFront.normal, Vector2.up);
}
else if (slopeHitBack)
{
isOnSlope = true;
slopeSideAngle = Vector2.Angle(slopeHitBack.normal, Vector2.up);
}
else
{
slopeSideAngle = 0.0f;
isOnSlope = false;
}
}
private void SlopeCheckVertical(Vector2 checkPos)
{
RaycastHit2D hit = Physics2D.Raycast(checkPos, Vector2.down, slopeCheckDistance, gLayerMask);
if (hit)
{
slopeNormalPerp = Vector2.Perpendicular(hit.normal).normalized;
slopeDownAngle = Vector2.Angle(hit.normal, Vector2.up);
if(slopeDownAngle != lastSlopeAngle)
{
isOnSlope = true;
}
lastSlopeAngle = slopeDownAngle;
Debug.DrawRay(hit.point, slopeNormalPerp, Color.blue);
Debug.DrawRay(hit.point, hit.normal, Color.green);
}
if (slopeDownAngle > maxSlopeAngle || slopeSideAngle > maxSlopeAngle)
{
canWalkOnSlope = false;
}
else
{
canWalkOnSlope = true;
}
if (isOnSlope && canWalkOnSlope && HorizontalValue == 0.0f)
{
rb2d.sharedMaterial = fullFriction;
}
else
{
rb2d.sharedMaterial = noFriction;
}
}
void Update()
{
if(slopeDownAngle != 0)
{
isOnSlope = true;
} else {
isOnSlope = false;
}
if (CanMove() == true){
HorizontalValue = Input.GetAxisRaw("Horizontal");
}
}
void FixedUpdate()
{
Gcheck();
Move(HorizontalValue, Crouch);
SlopeCheck();
}
Rigidbody>
Mass:0.5
BodyType: Dynamic
LinearDrag: 0
AngularDrag: 0
Gravity: 11
FreezeRotation: Only Z axis
::Friction Is Handled In The Movement Code::
But, when I finished the character got stuck again,
so I tried multiplying the slopeNormalPerp by a variable(MultSlope) and he just bounced up and down if made made it too high and if it was too low nothing happened.
I tried messing with varibles such as the ground-checking circles size, various colliders, the aforementioned MultSlope ,and slopeCheckDistance...
Nothing Helped...
I've been working on this for 7 months(with breaks working on other code) and I have improved greatly in coding, but I still can't fix it.
I tried messing with every relevant variable, watching the video many time, downloading and copy-pasting the code ,and following other tutorials of the slope code, No Dice.
Related
So basically what i am trying to do is create an animation script that does not just take simple direction like Up(0,1),Down(0,-1),Left(-1,0),Right(1,0)(Those numbers being vectors) but to have range of directions for to fill in the gap between those directions and play the more dominant direction Up,Down,Left,Right.
So each quarter section below to be set to an animation.
I have created a few scripts to try and achieve this i came up with one that wasn't perfect but it did work when dragging the enemies around in the scene editor while the game was running. When using their movements scripts for their movement it did not work. The animation script is below and underneath that how i move the enemies.
Below would be how i calculate the direction the enemy was moving:
IEnumerator directionFinder()
{
// while (true)
//{
Vector3 previousPosition = transform.position;
yield return new WaitForSeconds(1/10);
currentPosition = transform.position;
currentPosition.x = currentPosition.x - previousPosition.x;
currentPosition.y = currentPosition.y - previousPosition.y;
currentPosition.z = 0f;
angle = (Mathf.Atan2(currentPosition.y, currentPosition.x) * Mathf.Rad2Deg);
if(angle < 0)
{
angle = Mathf.Abs(angle) + 180;
}
// }
}
Then this is what calculated which animation to use:
void animationDirection()
{
if (angle == 0)
{
anim.SetInteger("Move", currentAnim);
}
if (angle > 45 && angle <135)//W
{
anim.SetInteger("Move", 1);
currentAnim = 1;
}
else if (angle > 135 && angle < 225)//A
{
anim.SetInteger("Move", 2);
currentAnim = 2;
}
else if (angle > 225 && angle < 315)//S
{
anim.SetInteger("Move", 3);
currentAnim = 3;
}
else if((angle < 45 && angle >= 0) || (angle > 315 && angle <= 0))//D
{
anim.SetInteger("Move", 4);
currentAnim = 4;
}
}
This using the code below it would move to the waypoint that was selected via the rest of my code that would just loop through a set of waypoints changing the waypoint when it arrived at one.
transform.position = Vector2.MoveTowards(transform.position, waypoints[waypointNUmber].transform.position, speed * Time.deltaTime);
Below I tried another way but it did not work and created weird buggy animations:
IEnumerator directionalAnimation()
{
while (true)
{
Debug.Log("working");
Vector2 previousPosition = transform.position;
yield return new WaitForSeconds(1/10);
Vector2 currentPosition = transform.position;
Vector2 direction = (previousPosition - currentPosition).normalized;
float moveX = direction.x;
float moveY = direction.y;
if (moveX < 0)
{
moveXNegative = true;
moveX = Mathf.Abs(moveX);
}
if (moveY < 0)
{
moveYNegative = true;
moveY = Mathf.Abs(moveY);
}
if (direction.magnitude != 0)
{
if (moveX > moveY)
{
if (moveXNegative)
{
//left
Walking = true;
anim.SetInteger("Move", 2);
moveYNegative = false;
}
else
{
//Right
Walking = true;
anim.SetInteger("Move", 4);
moveYNegative = false;
}
}
else if (moveY > moveX)
{
if (moveYNegative)
{
//Down
Walking = true;
anim.SetInteger("Move", 3);
}
else
{
//Up
Walking = true;
anim.SetInteger("Move", 1);
}
}
}
else
{
source.Pause();
Walking = false;
}
if (Walking)
{
source.UnPause();
}
}
}
Hey guys my question is in the title. Basically when I press play everything is OK, the ball starts to go up without shaking, but when I start swiping to change position it starts shaking.
I already tried different things like changing to FixedUpdate() or resetting the player, but it doesn't change. Btw there is no animation on the ball. Can you help me?
Here is the script with the swipe parameters :
public class Swipe : MonoBehaviour
{
private const float DEADZONE = 100.0f;
public static Swipe Instance { set; get; }
private bool tap, swipeLeft, swipeRight, swipeUp, swipeDown;
private Vector2 startTouch, swipeDelta;
public bool Tap { get { return tap; } }
public Vector2 SwipeDelta { get { return swipeDelta; } }
public bool SwipeLeft { get { return swipeLeft; } }
public bool SwipeRight { get { return swipeRight; } }
public bool SwipeUp { get { return swipeUp; } }
public bool SwipeDown { get { return swipeDown; } }
private void Awake()
{
Instance = this;
}
private void Update()
{
// Reseting all the booleans
tap = swipeLeft = swipeRight = swipeDown = swipeUp = false;
#region Stadalone Inputs
if (Input.GetMouseButtonDown(0))
{
tap = true;
startTouch = Input.mousePosition;
}
else if (Input.GetMouseButtonUp(0))
{
startTouch = swipeDelta = Vector2.zero;
}
#endregion
#region Mobile Inputs
if (Input.touches.Length != 0)
{
if (Input.touches[0].phase == TouchPhase.Began)
{
tap = true;
startTouch = Input.mousePosition;
}
else if (Input.touches[0].phase == TouchPhase.Ended || Input.touches[0].phase == TouchPhase.Canceled)
{
startTouch = swipeDelta = Vector2.zero;
}
}
#endregion
// Calculate The Distance
swipeDelta = Vector2.zero;
if (startTouch != Vector2.zero)
{
if (Input.touches.Length != 0)
{
swipeDelta = Input.touches[0].position - startTouch;
}
else if (Input.GetMouseButton(0))
{
swipeDelta = (Vector2)Input.mousePosition - startTouch;
}
}
// Did we cross the deadzone ?
if (swipeDelta.magnitude > DEADZONE)
{
// Which direction ?
float x = swipeDelta.x;
float y = swipeDelta.y;
if (Mathf.Abs(x) > Mathf.Abs(y))
{
// Left or Right
if (x < 0)
swipeLeft = true;
else
swipeRight = true;
}
else
{
// Up or Down
if (y < 0)
swipeDown = true;
else
swipeUp = true;
}
startTouch = swipeDelta = Vector2.zero;
}
}
}
And this the part of the script in Update() or (FixedUpdate(), it doesn't change anything) used to make it move one side or the other on the player :
// Gather the inputs in which tube we should be
if (Swipe.Instance.SwipeLeft)
MoveTube(false);
if (Swipe.Instance.SwipeRight)
MoveTube(true);
// Calculate where we should be in the future
Vector3 targetPosition = transform.position.y * Vector3.up;
if (desiredTube == 0)
targetPosition += Vector3.left * TUBE_DISTANCE;
else if (desiredTube == 2)
targetPosition += Vector3.right * TUBE_DISTANCE;
// Let's calculate our move delta
Vector3 moveVector = Vector3.zero;
moveVector.x = (targetPosition - transform.position).normalized.x * speed;
moveVector.y = speed;
// Move the ball
controller.Move(moveVector * Time.deltaTime);
}
private void MoveTube(bool goingRight)
{
desiredTube += (goingRight) ? 1 : -1;
desiredTube = Mathf.Clamp(desiredTube, 0, 2);
}
I believe you may be having issue here:
// Gather the inputs in which tube we should be
if (Swipe.Instance.SwipeLeft)
MoveTube(false);
if (Swipe.Instance.SwipeRight)
MoveTube(true);
Since Update() is invoked once per frame, this means this will be checked several times per second. So it may be changing the position of the player several times per second, giving this shaking effect you mention.
What you could try is to restrict the times the player can swipe per second.
private float SwipeRate = 0.1f;
private float NextSwipe = 0.0f;
Update(){
if (Swipe.Instance.SwipeLeft && Time.time > NextSwipe)
{
NextSwipe = Time.time+SwipeRate;
MoveTube(false);
}
if (Swipe.Instance.SwipeRight && Time.time > NextSwipe)
{
NextSwipe = Time.time+SwipeRate;
MoveTube(true);
}
}
Edit:
private void MoveTube(bool goingRight)
{
desiredTube += (goingRight) ? 1 : -1;
desiredTube = Mathf.Clamp(desiredTube, 0, 2);
// Calculate where we should be in the future
Vector3 targetPosition = transform.position.y * Vector3.up;
if (desiredTube == 0)
targetPosition += Vector3.left * TUBE_DISTANCE;
else if (desiredTube == 2)
targetPosition += Vector3.right * TUBE_DISTANCE;
// Let's calculate our move delta
Vector3 moveVector = Vector3.zero;
moveVector.x = (targetPosition - transform.position).normalized.x * speed;
moveVector.y = speed;
// Move the ball
controller.Move(moveVector * Time.deltaTime);
}
I found how to solve the problem. So basically I was using the same speed variable to move my ball on the x and y axis and it seems that it created some “switch problem” for unity. So I just created 2 different variables for the speed and I solved the bug like this.
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);
}
So, I'm generating a Vector2 using Unity's Random.Range, this is basically the x and y value of the direction the mobile should be moving.
m_CurrentMovementInput = new Vector2
(Random.Range(-0.75f, 0.75f), Random.Range(-0.75f, 0.75f));
The problem is the mobiles are only moving in diagonal angles. Which makes it seem like when it produces the random it's producing like..
(-0.35f, -0.35f) or (0.35f, -0.35f) or (-0.35f, 0.35f)
Which makes little sense to me as I understand the random function.
I'm sure I can get the desired behaviour by only changing one at a time, but I'd still like to understand its current behavior.
Edit: I believe this is all the relevant code. Sorry it took so long had to go get it from the repo.
void ProcessMovement()
{
ModifyComputerMovement(m_CurrentMovementInput.x, m_CurrentMovementInput.x);
}
float ModifyMovementInput(float input)
{
return input * m_MovementSpeedBase;
}
void RandomizeMovementInput()
{
m_CurrentMovementInput = new Vector2
(Random.Range(-0.75f, 0.75f), Random.Range(-0.75f, 0.75f));
if(RandomBoolean)
{
m_CurrentMovementInput += new Vector2
(Random.Range(-0.05f, 0.05f), Random.Range(-0.05f, 0.05f));
}
}
void ModifyComputerMovement(float x, float y)
{
m_VerticalInput = x;
m_HorizontalInput = y;
if ((m_VerticalInput == 0 && m_HorizontalInput == 0))
{
m_IsMoving = false;
}
else { m_IsMoving = true; }
UpdateCpuLocation();
}
bool m_ShouldRun;
bool m_ShouldSprint;
void UpdateCpuLocation()
{
if (!IsMoving())
m_CurrentMoveType = MovementType.None;
else
m_CurrentMoveType = MovementType.Walk;
m_DeltaVector = new Vector3
(
ModifyMovementInput(m_VerticalInput),
m_IsJumping ? ComputeJumpVelocity() : ApplyGravity(),
ModifyMovementInput(m_HorizontalInput)
);
m_GammaVector =
transform.forward * m_DeltaVector.x + transform.right * m_DeltaVector.z;
m_DeltaVector = new Vector3
(m_GammaVector.x, m_DeltaVector.y, m_GammaVector.z);
if (m_ShouldRun && IsMoving())
{
if (m_Controller.isGrounded)
{
m_CurrentMoveType = MovementType.Run;
m_DeltaVector *= m_RunSprintFactor;
if (m_ShouldSprint && IsMoving())
{
m_CurrentMoveType = MovementType.Sprint;
m_DeltaVector *= m_RunSprintFactor;
}
}
}
m_VectorShift = !m_Controller.isGrounded ?
(m_DeltaVector * Time.deltaTime) * m_JumpModifier : (m_DeltaVector * Time.deltaTime);
if (m_Controller.isGrounded)
m_VectorShift *= (m_PlayerState.GetCurrentEnergyLevelRatio());
m_VectorShift = new Vector3
(
m_VectorShift.x,
m_VectorShift.y,
m_VectorShift.z
);
#region Debug
//Debug.Log("Vector Shift: " + m_VectorShift);
//Debug.Log("Vector Shift Breakdown:");
/*Debug.Log
(String.Format
("VectorShift (X): {0} | VectorShift (Y): {1} | VectorShift (Z): {2}",
(double)m_VectorShift.x, (double)m_VectorShift.y, (double)m_VectorShift.z));*/
#endregion
if (m_PlayerState.GetCurrentEnergyLevelRatio() < m_MinimumEnergyThreshold)
m_VectorShift *= m_LowStamMoveModulus;
//m_MoveEventArg =
//new PlayerMoveActionEventArgs(m_VectorShift, GetCurrentMovementType);
if (m_IsMoving)
{
//EventDispatcher.InvokeMoveAction(m_MoveEventArg);
}
m_VectorShift = m_VectorShift * (Time.deltaTime * m_TimeWarpModifier);
m_Controller.Move(m_VectorShift);
}
Edit, Part II
So, the only thing that is really different is this:
void QueryPlayerInput()
{
m_VerticalInput = Input.GetAxis("Vertical");
m_HorizontalInput = Input.GetAxis("Horizontal");
if ((m_VerticalInput == 0 && m_HorizontalInput == 0))
{
m_IsMoving = false;
}
else { m_IsMoving = true; }
UpdatePlayerLocation();
}
Im making a platform game with Unity and Im programming with C#. I have a Ball Control script which handles the input and the physics behind its continuous bouncing. I also have a BounceTrigger script which make the ball stop and then make it bounce again. Im trying to implement a respawn with the player should be respawning at the last platform not destructible he has bounced over.
Ball Control Script
public float velocity = 2;
bool alreadyBounced;
bool boost;
float boostMultiplier;
Vector3 boostVelocityAdd;
int fallY = 10;
BounceTrigger platform;
// Update is called once per frame
void Update ()
{
alreadyBounced = false;
float appliedVelocity = velocity * (boost ? boostMultiplier : 1);
Vector3 direction = Vector3.zero;
if(Input.GetKeyDown(KeyCode.LeftArrow) || Input.GetKeyDown(KeyCode.A)) { direction = Vector3.left; rigidbody.AddForce(direction * appliedVelocity, ForceMode.VelocityChange);}
if(Input.GetKeyDown(KeyCode.RightArrow) || Input.GetKeyDown(KeyCode.D)) { direction = Vector3.right; rigidbody.AddForce(direction * appliedVelocity, ForceMode.VelocityChange);}
if(Input.GetKeyDown(KeyCode.UpArrow) || Input.GetKeyDown(KeyCode.W)) { direction = Vector3.forward; rigidbody.AddForce(direction * appliedVelocity, ForceMode.VelocityChange);}
if(Input.GetKeyDown(KeyCode.DownArrow) || Input.GetKeyDown(KeyCode.S)) { direction = -Vector3.forward; rigidbody.AddForce(direction * appliedVelocity, ForceMode.VelocityChange); }
if(Input.GetKeyUp(KeyCode.LeftArrow) || Input.GetKeyUp(KeyCode.A)) { direction = -Vector3.left; rigidbody.AddForce(direction * appliedVelocity, ForceMode.VelocityChange); }
if(Input.GetKeyUp(KeyCode.RightArrow) || Input.GetKeyUp(KeyCode.D)){ direction = -Vector3.right; rigidbody.AddForce(direction * appliedVelocity, ForceMode.VelocityChange); }
if(Input.GetKeyUp(KeyCode.UpArrow) || Input.GetKeyUp(KeyCode.W)) { direction = -Vector3.forward; rigidbody.AddForce(direction * appliedVelocity, ForceMode.VelocityChange); }
if(Input.GetKeyUp(KeyCode.DownArrow) || Input.GetKeyUp(KeyCode.S)) { direction = Vector3.forward; rigidbody.AddForce(direction * appliedVelocity, ForceMode.VelocityChange); }
CheckFalling ();
}
public void CheckFalling(){
if(this.transform.position.y < fallY){
Respawn();
}
}
public void Respawn(){
this.transform.position = lastPlatform.transform.position + Vector3.up;
}
public void Bounce(BounceTrigger platform, float upVelocity) {
var reboteGO = (GameObject) GameObject.FindWithTag ("TextoRebote");
var reboteComp = reboteGO.GetComponent<BounceCounter>();
if(!alreadyBounced)
{
if(!platform.isDestructible){
lastPlatform = platform;
}
Debug.Log("Bounce");
alreadyBounced = true;
reboteComp.AumentarRebote();
float downVelocity = rigidbody.velocity.y;
rigidbody.AddForce(Vector3.up * (-downVelocity + upVelocity), ForceMode.VelocityChange);
ResetBoost();
}
}
public void Boost(float multiplier){
if(!boost){
Debug.Log("Boost");
StartCoroutine(BoostCoroutine(multiplier));
}
}
public void ResetBoost(){
if(boost){
Debug.Log("Reset boost");
boost = false;
Vector3 velocityAdd = rigidbody.velocity;
velocityAdd.x = velocityAdd.x / boostMultiplier * (boostMultiplier - 1);
velocityAdd.z = velocityAdd.z / boostMultiplier * (boostMultiplier - 1);
velocityAdd.y = 0;
rigidbody.AddForce(-velocityAdd, ForceMode.VelocityChange);
}
}
public void RestarVida(){
var vidaGO = (GameObject) GameObject.FindWithTag ("TextoVida");
var vidaComp = vidaGO.GetComponent<LifeCounter>();
vidaComp.RestarVida ();
}
IEnumerator BoostCoroutine(float multiplier){
yield return 0;
yield return new WaitForFixedUpdate();
boost = true;
boostMultiplier = multiplier;
Vector3 velocityAdd = rigidbody.velocity;
Debug.Log(velocityAdd);
velocityAdd.x = velocityAdd.x * (boostMultiplier - 1);
velocityAdd.z = velocityAdd.z * (boostMultiplier - 1);
velocityAdd.y = 0;
rigidbody.AddForce(velocityAdd, ForceMode.VelocityChange);
Debug.Log(velocityAdd);
}
Bounce Trigger script:
`
public float upVelocity = 10;
public bool isDestructible = false;
public virtual void OnTriggerEnter(Collider collider){
collider.GetComponent<BallControl>().Bounce(this, upVelocity);
}
when I compile this I get a nullReferenceException
`
You have a global variable BounceTrigger platform; instead of BounceTrigger lastPlatform;, so lastPlatform don't exists anywhere in your code.