#unity3d #gravity
#unity3d #gravity
Вопрос:
Я действительно надеюсь, что вы, ребята, сможете помочь мне с моей проблемой, это было мое последнее средство, и я очень расстроен.
Я создаю 2D-игру с сайдскроллером, и при кодировании файла player я столкнулся с очень раздражающей вещью, в которой я не знаю, в чем проблема. Все остальное в плеере в порядке, происходит то, что если игрок идет по наклону, а затем отрывается; с гравитацией (я предполагаю) что-то не так, и когда вы в воздухе, он просто плывет вниз вместо падения; также, если вы прыгаете (после ходьбы по наклону), он просто совершает крошечный прыжок. Я несколько раз отлаживал весь файл и, похоже, не могу разобраться.
Если кто-нибудь, пожалуйста, поможет, я добавлю весь файл проигрывателя. Если у вас есть 2D-игра с сайдскроллером в Unity, вы можете просто поместить этот файл в gameobject с Rigidbody2D и isKinemic верен..
using UnityEngine;
using System.Collections;
using System;
public class PlayerControl : MonoBehaviour {
private Animator anim;
public static PlayerControl instance;
public static bool isShooting;
[HideInInspector]
public bool facingRight;
private float normalSpeed;
private static readonly float slopeLimitTangent = Mathf.Tan(75f * Mathf.Deg2Rad);
public float maxSpeed = 8f;
private float speedAccelerationOnGround = 10f;
private float speedAccelerationInAir = 5f;
private Vector2 velocity {get {return vel;}}
public int health = 100;
private bool isDead;
private const float skinWidth = .02f;
private const int horizRays = 8;
private const int vertRays = 4;
public enum JumpBehavior {
JumpOnGround,
JumpAnywhere,
CantJump
};
public JumpBehavior jumpWhere;
private float jumpIn;
public float jumpFreq = 0.25f;
public float jumpMag = 16;
public LayerMask whatIsGround;
private bool grounded { get { return colBelow; } }
private bool cooldown;
public GameObject standingOn {get; private set;}
public Vector3 platformVelocity {get;private set;}
public bool canJump { get {
if (jumpWhere == JumpBehavior.JumpAnywhere)
return jumpIn <= 0;
if (jumpWhere == JumpBehavior.JumpOnGround)
return grounded;
return false;
}
}
public bool colRight { get; set;}
public bool colLeft { get; set;}
public bool colAbove{ get; set;}
public bool colBelow{ get; set;}
public bool upSlope{ get; set;}
public bool downSlope{get;set;}
public float slopeAngle {get;set;}
public bool hasCollisions { get { return colRight || colLeft || colAbove || colBelow; }
}
private float
vertDistanceBetweenRays,
horizDistanceBetweenRays;
private Vector3 raycastTopLeft;
private Vector3 raycastBottomRight;
private Vector3 raycastBottomLeft;
private Vector2 maxVelocity = new Vector2(float.MaxValue,
float.MaxValue);
private Vector2 vel;
[Range(0, 90)]
public float slopeLimit = 30;
public float gravity = -15;
private GameObject lastStandingOn;
private Vector3 activeGlobalPlatformPoint;
private Vector3 activeLocalPlatformPoint;
public static int scene = 0;
void Start () {
instance = this;
anim = GetComponent<Animator> ();
float colliderWidth = GetComponent<BoxCollider2D>().size.x * Mathf.Abs
(transform.localScale.x) - (2 * skinWidth);
horizDistanceBetweenRays = colliderWidth / (vertRays - 1);
float colliderHeight = GetComponent<BoxCollider2D>().size.y * Mathf.Abs
(transform.localScale.y) - (2 * skinWidth);
vertDistanceBetweenRays = colliderHeight / (horizRays - 1);
}
void Update () {
if (!isDead)
HandleInput();
float movementFactor = grounded ? speedAccelerationOnGround : speedAccelerationInAir;
if (isDead)
HorizForce(0);
else
HorizForce(Mathf.Lerp(velocity.x, normalSpeed * maxSpeed, Time.deltaTime * movementFactor));
anim.SetBool("Grounded", grounded);
anim.SetBool("Dead", isDead);
anim.SetFloat("Speed", Mathf.Abs(velocity.x) / maxSpeed);
}
public void LateUpdate() {
jumpIn -= Time.deltaTime;
vel.y = gravity * Time.deltaTime;
Move (vel * Time.deltaTime);
}
public void AddForce(Vector2 force) {
vel = force;
}
public void SetForce(Vector2 force) {
vel = force;
}
public void HorizForce(float x) {
vel.x = x;
}
public void VertForce(float y) {
vel.y = y;
}
public void Jump() {
AddForce(new Vector2(0, jumpMag));
jumpIn = jumpFreq;
anim.SetTrigger("Jump");
}
void HandleInput() {
float h = Input.GetAxis("Horizontal");
normalSpeed = h;
if (h < 0) {
if (!facingRight)
Flip ();
facingRight = true;
} else
if (h > 0) {
if (facingRight)
Flip ();
facingRight = false;
} else
normalSpeed = 0;
if (canJump amp;amp; Input.GetButtonDown("Jump"))
Jump();
if (Input.GetButton("melee") amp;amp; !Input.GetButtonDown ("Fire1") amp;amp; MeleeAttack.canHit) {
anim.SetTrigger ("Attack");
MeleeAttack.canHit = false;
MeleeAttack.instance.cooldown ();
}
}
private void Flip() {
transform.localScale = new Vector3(-transform.localScale.x, transform.localScale.y, transform.localScale.z);
facingRight = transform.localScale.x > 0;
}
void ResetColliders() {
colLeft = false;
colRight = false;
colAbove = false;
colBelow = false;
colLeft = false;
slopeAngle = 0;
}
void Move(Vector2 deltaMove) {
bool wasGrounded = colBelow;
ResetColliders();
HandlePlatforms ();
CalcRayOrigins();
if (deltaMove.y < 0 amp;amp; wasGrounded)
HandleVerticalSlope(ref deltaMove);
if (Mathf.Abs(deltaMove.x) > 0.001f)
MoveHoriz(ref deltaMove);
MoveVert(ref deltaMove);
//CorrectHorizPlacement(ref deltaMove, true);
//CorrectHorizPlacement(ref deltaMove, false);
transform.Translate(deltaMove, Space.World);
if (Time.deltaTime > 0)
vel = deltaMove / Time.deltaTime;
vel.x = Mathf.Min(vel.x, maxVelocity.x);
vel.y = Mathf.Min(vel.y, maxVelocity.y);
if (upSlope)
vel.y = 0;
if (standingOn != null) {
activeGlobalPlatformPoint = transform.position;
activeLocalPlatformPoint = standingOn.transform.InverseTransformPoint(transform.position);
if (lastStandingOn != standingOn) {
if (lastStandingOn != null)
lastStandingOn.SendMessage("ControllerExit2D", this, SendMessageOptions.DontRequireReceiver);
standingOn.SendMessage("ControllerEnter2D", this, SendMessageOptions.DontRequireReceiver);
lastStandingOn = standingOn;
} else if (standingOn != null)
standingOn.SendMessage("ControllerStay2D", this, SendMessageOptions.DontRequireReceiver);
else if (lastStandingOn != null) {
lastStandingOn.SendMessage("ControllerExit2D", this, SendMessageOptions.DontRequireReceiver);
lastStandingOn = null;
}
}
}
void MoveHoriz(ref Vector2 deltaMove) {
bool goingRight = deltaMove.x > 0;
float rayDistance = Mathf.Abs (deltaMove.x) skinWidth;
Vector2 rayDirection = goingRight ? Vector2.right : -Vector2.right;
Vector3 rayOrigin = goingRight ? raycastBottomRight : raycastBottomLeft;
for (int i = 0; i < horizRays; i ) {
Vector2 rayVect = new Vector2(rayOrigin.x, rayOrigin.y (i * vertDistanceBetweenRays));
Debug.DrawRay(rayVect, rayDirection * rayDistance, Color.red);
RaycastHit2D raycastHit = Physics2D.Raycast(rayVect, rayDirection, rayDistance, whatIsGround);
if (!raycastHit) continue;
if (i == 0 amp;amp; HandleHorizontalSlope(ref deltaMove, Vector2.Angle(raycastHit.normal, Vector2.up), goingRight))
break;
deltaMove.x = raycastHit.point.x - rayVect.x;
rayDistance = Mathf.Abs (deltaMove.x);
if (goingRight) {
deltaMove.x -= skinWidth;
colRight = true;
} else {
deltaMove.x = skinWidth;
colLeft = true;
}
if (rayDistance < skinWidth .0001f)
break;
}
}
private void HandlePlatforms() {
if (standingOn != null) {
Vector3 newGlobalPlatformPoint = standingOn.transform.TransformPoint(activeLocalPlatformPoint);
Vector3 moveDistance = newGlobalPlatformPoint - activeGlobalPlatformPoint;
if (moveDistance != Vector3.zero)
transform.Translate(moveDistance, Space.World);
platformVelocity = (newGlobalPlatformPoint - activeGlobalPlatformPoint) / Time.deltaTime;
} else
platformVelocity = Vector3.zero;
standingOn = null;
}
private void MoveVert(ref Vector2 deltaMovement) {
bool isGoingUp = deltaMovement.y > 0;
float rayDistance = Mathf.Abs(deltaMovement.y) skinWidth;
Vector2 rayDirection = isGoingUp ? Vector2.up : -Vector2.up;
Vector2 rayOrigin = isGoingUp ? raycastTopLeft : raycastBottomLeft;
rayOrigin.x = deltaMovement.x;
float standingOnDistance = float.MaxValue;
for (int i = 0; i < vertRays; i ) {
Vector2 rayVector = new Vector2(rayOrigin.x (i * horizDistanceBetweenRays), rayOrigin.y);
Debug.DrawRay(rayVector, rayDirection * rayDistance, Color.red);
RaycastHit2D rayCastHit = Physics2D.Raycast(rayVector, rayDirection, rayDistance, whatIsGround);
if (!rayCastHit)
continue;
if (!isGoingUp) {
float verticalDistanceToHit = transform.position.y - rayCastHit.point.y;
if (verticalDistanceToHit < standingOnDistance) {
standingOnDistance = verticalDistanceToHit;
standingOn = rayCastHit.collider.gameObject;
}
}
deltaMovement.y = rayCastHit.point.y - rayVector.y;
rayDistance = Mathf.Abs(deltaMovement.y);
if (isGoingUp) {
deltaMovement.y -= skinWidth;
colAbove = true;
} else {
deltaMovement.y = skinWidth;
colBelow = true;
}
if (!isGoingUp amp;amp; deltaMovement.y > .0001f)
upSlope = true;
if (rayDistance < skinWidth .0001f)
break;
}
}
private void HandleVerticalSlope(ref Vector2 deltaMove) {
float center = (raycastBottomLeft.x raycastBottomRight.x) / 2;
Vector2 direction = -Vector2.up;
float slopeDistance = slopeLimitTangent (raycastBottomRight.x - center);
Vector2 slopeRayVector = new Vector2(center, raycastBottomLeft.y);
Debug.DrawRay(slopeRayVector, direction * slopeDistance, Color.yellow);
RaycastHit2D rayCastHit = Physics2D.Raycast(slopeRayVector, direction, slopeDistance, whatIsGround);
if (!rayCastHit)
return;
float angle = Vector2.Angle(rayCastHit.normal, Vector2.up);
if (Mathf.Abs (angle) < .0001f)
return;
downSlope = true;
slopeAngle = angle;
deltaMove.y = rayCastHit.point.y - slopeRayVector.y;
transform.rotation = Quaternion.Euler (0, 0, facingRight ? angle : -angle);
}
private bool HandleHorizontalSlope(ref Vector2 deltaMove, float angle, bool isGoingRight) {
if (Mathf.RoundToInt(angle) == 90)
return false;
if (angle > slopeLimit) {
deltaMove.x = 0;
return true;
}
if (deltaMove.y > .07f)
return true;
deltaMove.x = isGoingRight ? -skinWidth : skinWidth;
deltaMove.y = Mathf.Abs(Mathf.Tan(angle * Mathf.Deg2Rad) * deltaMove.x);
upSlope = true;
colBelow = true;
return true;
}
void CalcRayOrigins() {
Vector2 size = new Vector2(GetComponent<BoxCollider2D>().size.x * Mathf.Abs(transform.localScale.x), GetComponent<BoxCollider2D>().size.y * Mathf.Abs(transform.localScale.y)) / 2;
Vector2 center = new Vector2(GetComponent<BoxCollider2D>().center.x * transform.localScale.x, GetComponent<BoxCollider2D>().center.y * transform.localScale.y);
raycastTopLeft = transform.position new Vector3(center.x - size.x skinWidth, center.y size.y - skinWidth);
raycastBottomRight = transform.position new Vector3(center.x size.x - skinWidth, center.y - size.y skinWidth);
raycastBottomLeft = transform.position new Vector3(center.x - size.x skinWidth, center.y - size.y skinWidth);
}
void CorrectHorizPlacement(ref Vector2 deltaMove, bool isRight) {
float halfWidth = (GetComponent<BoxCollider2D> ().size.x * transform.localScale.x) / 2f;
Vector3 rayOrigin = isRight ? raycastBottomRight : raycastBottomLeft;
if (isRight)
rayOrigin.x -= (halfWidth skinWidth);
else
rayOrigin.x = (halfWidth skinWidth);
Vector2 rayDirection = isRight ? Vector2.right : -Vector2.right;
float offset = 0;
for (int i = 1; i < horizRays - 1; i ) {
Vector2 rayVector = new Vector2(deltaMove.x rayOrigin.x, deltaMove.y rayOrigin.y (i * vertDistanceBetweenRays));
RaycastHit2D raycastHit = Physics2D.Raycast(rayVector, rayDirection, halfWidth, whatIsGround);
if (!raycastHit) continue;
offset = isRight ? ((raycastHit.point.x - transform.position.x) - halfWidth) : (halfWidth - (transform.position.x - raycastHit.point.x));
deltaMove.x = offset;
}
}
}
пожалуйста, кто-нибудь, помогите.