博主Unity版本为5.4.4
这篇文章主要针对youtub上的一个专题系列的视频中的代码翻译和自己的一些理解,主要是是通过代码控制2d游戏物体的移动,碰撞,重力。视频地址:https://www.youtube.com/watch?v=MbWK8bCAU2w
首先简单的搭一下场景
新建几个quad,和材质,红色的为player,白色的为场景物体。
然后新建俩个C#脚本,分别为Player,Controller2D
第一部分:
using UnityEngine;
using System.Collections;
//自动给player添加Controller2D脚本组件
[RequireComponent(typeof(Controller2D))]
public class Player : MonoBehaviour {
public float moveSpeed = 6f;//移动速度
public float gravity;//重力加速度
private Vector3 velocity;//player的速度
private Controller2D controller;
void Start(){
controller = GetComponent<Controller2D> ();
}
void Update(){
Vector2 input = new Vector2 (Input.GetAxisRaw("Horizontal"),Input.GetAxisRaw("Vertical"));//获取输入轴的值
velocity.x = input.x * moveSpeed;
velocity.y += gravity * Time.deltaTime;//通过代码控制重力
controller.Move (velocity*Time.deltaTime);//移动
}
}
通过代码模拟重力,velocity*Time.deltaTime速度乘以时间得到每一帧的移动量
using UnityEngine;
using System.Collections;
//自动添加BoxCollider2D组件
[RequireComponent(typeof(BoxCollider2D))]
public class Controller2D : MonoBehaviour {
public LayerMask collisionMask;//射线碰撞检测层
public int horizontalRayCount = 4;//水平方向的射线数
public int verticalRayCount = 4;//竖直方向的射线数
private float horizontalRaySpacing;//水平方向的射线间距
private float verticalRaySpacing;//竖直方向的射线间距
private const float skillWidth = .015f;
private BoxCollider2D collider;
private RaycastOrigins raycastOrigins;//射线的源点
void Start(){
collider = GetComponent<BoxCollider2D> ();
CalculateRaySpacing ();
}
//Bounds在C#中是struct类型也就是值类型,所以每帧都要更新射线源点
private void UpdateRaycastOrigins(){
Bounds bounds = collider.bounds;//得到player的包围盒
bounds.Expand (skillWidth*-2);//将包围盒缩小,就像又包了一层
//得到射线源点
raycastOrigins.bottomLeft = new Vector2 (bounds.min.x,bounds.min.y);
raycastOrigins.bottomRight = new Vector2 (bounds.max.x,bounds.min.y);
raycastOrigins.topLeft = new Vector2 (bounds.min.x,bounds.max.y);
raycastOrigins.topRight = new Vector2 (bounds.max.x,bounds.max.y);
}
private void CalculateRaySpacing(){//计算水平和竖直的射线间距
Bounds bounds = collider.bounds;
bounds.Expand (skillWidth*-2);//缩小包围盒
horizontalRayCount = Mathf.Clamp (horizontalRayCount,2,int.MaxValue);//限定射线数量
verticalRayCount = Mathf.Clamp (verticalRayCount,2,int.MaxValue);
horizontalRaySpacing = bounds.size.y / (horizontalRayCount - 1);//计算间距
verticalRaySpacing = bounds.size.x / (verticalRayCount - 1);
}
private void VerticalCollisions(ref Vector3 velocity){//竖直方向的射线检测
float directionY = Mathf.Sign (velocity.y);//通过y来判断是跳跃还是下落
float rayLength = Mathf.Abs (velocity.y)+skillWidth;//射线的长度
for (int i = 0; i < verticalRayCount; i++) {
Vector2 rayOrigin = (directionY == -1) ? raycastOrigins.bottomLeft : raycastOrigins.topLeft;//通过方向来选择射线的起点
rayOrigin += Vector2.right * (verticalRaySpacing * i + velocity.x);//加上x方向的偏移
RaycastHit2D hit = Physics2D.Raycast (rayOrigin,Vector2.up*directionY,rayLength,collisionMask);//检测碰撞
Debug.DrawRay (rayOrigin,Vector2.up*directionY*rayLength,Color.red);
if (hit) {//如果发生碰撞
velocity.y = (hit.distance-skillWidth)*directionY;//移动距离变为碰撞点距物体的距离
rayLength = hit.distance;
}
}
}
private void HorizontalCollisions(ref Vector3 velocity){//水平方向检测碰撞
float directionX = Mathf.Sign (velocity.x);//通过x来判断是向左还是右
float rayLength = Mathf.Abs (velocity.x)+skillWidth;//射线的长度
for (int i = 0; i < horizontalRayCount; i++) {
Vector2 rayOrigin = (directionX == -1) ? raycastOrigins.bottomLeft : raycastOrigins.bottomRight;//通过方向来选择射线的起点
rayOrigin += Vector2.up * (horizontalRaySpacing * i);//
RaycastHit2D hit = Physics2D.Raycast (rayOrigin,Vector2.right*directionX,rayLength,collisionMask);//检测碰撞
Debug.DrawRay (rayOrigin,Vector2.right*directionX*rayLength,Color.red);
if (hit) {//如果发生碰撞
velocity.x = (hit.distance - skillWidth) * directionX;//移动距离变为碰撞点距物体的距离
rayLength = hit.distance;
}
}
}
public void Move(Vector3 velocity){//移动
UpdateRaycastOrigins ();//更新射线源点
if(velocity.x!=0)
HorizontalCollisions(ref velocity);
if(velocity.y!=0)
VerticalCollisions (ref velocity);//竖直方向检测碰撞
transform.Translate (velocity);//移动
}
struct RaycastOrigins{//射线源点
public Vector2 topLeft,topRight;
public Vector2 bottomLeft,bottomRight;
}
}
在这里我们使用射线检测的方式去处理碰撞,这段代码可能有点长,接下来画几个图帮助理解。
velocity.y是当前帧要移动的y方向的距离,加上skillWidth就是当前帧射线的探测长度,如果射线检测到了碰撞,则将velocity.y的值变为hit.distance-skillWidth,以保证不会穿透物体
这里水平方向跟竖直基本一样,这里需要注意一点,我们是在Move函数中先执行水平方向的检测再执行竖直方向的检测,因为竖直方向的射线源点带有x方向的偏移。如果先检测竖直方向的,那么x偏移量还没有被限制,此时加上skillWidth可能会大于与障碍物的距离,移动后,射线的位置会穿透到物体中,之后再检测竖直方向是就会误认为是地面而向上移动
第二部分: 加入跳跃和爬坡
using UnityEngine;
using System.Collections;
[RequireComponent(typeof(Controller2D))]
public class Player : MonoBehaviour {
public float jumpHeight = 4f;//起跳高度
public float timeToJumpApex = .4f;//到达高度的时间
public float moveSpeed = 6f;
public float velocityXSmoothing;
public float accelerationTimeAirBorne = .2f;//在空中水平移动的缓冲时间
public float accelerationTimeGrounded = .1f;//在地面水平移动的缓冲时间
private float gravity;//重力加速度
private float jumpVelocity;//跳跃速度
private Vector3 velocity;
private Controller2D controller;
void Start(){
controller = GetComponent<Controller2D> ();
gravity = -(2 * jumpHeight) / Mathf.Pow (timeToJumpApex,2);//s = V0t+(at)2/2
jumpVelocity = Mathf.Abs(gravity * timeToJumpApex);//VelocityFinal = Velocityinit+at
}
void Update(){
if (controller.collisions.above || controller.collisions.below) {
velocity.y = 0;
}
Vector2 input = new Vector2 (Input.GetAxisRaw("Horizontal"),Input.GetAxisRaw("Vertical"));
if (Input.GetKeyDown (KeyCode.Space) && controller.collisions.below) {//如果在地面则可以跳
velocity.y = jumpVelocity;
}
float targetVelocity = velocity.x = input.x * moveSpeed;
//平滑移动,velocity.x:当前速度,targetVelocity:目标速度,velocityXSmoothing:中间量不用理会,(controller.collisions.below)?accelerationTimeGrounded:accelerationTimeAirBorne:缓冲时间,值越大越慢
velocity.x = Mathf.SmoothDamp (velocity.x,targetVelocity,ref velocityXSmoothing,(controller.collisions.below)?accelerationTimeGrounded:accelerationTimeAirBorne);
velocity.y += gravity * Time.deltaTime;
controller.Move (velocity*Time.deltaTime);
}
}
这里我们重新修改了重力,通过跳跃高度和到达最大高度的时间来计算重力,其实就是高中物理上的公式,路程=初始速度x时间+加速度x时间的平方除以2,还有一个速度=初始速度+加速度x时间
using UnityEngine;
using System.Collections;
[RequireComponent(typeof(BoxCollider2D))]
public class Controller2D : MonoBehaviour {
public LayerMask collisionMask;//射线碰撞检测层
public CollisionInfo collisions;//记录玩家处于什么位置
public int horizontalRayCount = 4;//水平方向的射线数
public int verticalRayCount = 4;//竖直方向的射线数
public float maxClimbAngle = 80f;//可以行走的斜坡最大倾斜度
public float maxDescendAngle = 75f;
private float horizontalRaySpacing;//水平方向的射线间距
private float verticalRaySpacing;//竖直方向的射线间距
private const float skillWidth = .015f;
private BoxCollider2D collider;
private RaycastOrigins raycastOrigins;
void Start(){
collider = GetComponent<BoxCollider2D> ();
CalculateRaySpacing ();
}
private void UpdateRaycastOrigins(){
Bounds bounds = collider.bounds;
bounds.Expand (skillWidth*-2);
raycastOrigins.bottomLeft = new Vector2 (bounds.min.x,bounds.min.y);
raycastOrigins.bottomRight = new Vector2 (bounds.max.x,bounds.min.y);
raycastOrigins.topLeft = new Vector2 (bounds.min.x,bounds.max.y);
raycastOrigins.topRight = new Vector2 (bounds.max.x,bounds.max.y);
}
private void CalculateRaySpacing(){//计算水平和竖直的射线间距
Bounds bounds = collider.bounds;
bounds.Expand (skillWidth*-2);//缩小包围盒
horizontalRayCount = Mathf.Clamp (horizontalRayCount,2,int.MaxValue);//限定射线数量
verticalRayCount = Mathf.Clamp (verticalRayCount,2,int.MaxValue);
horizontalRaySpacing = bounds.size.y / (horizontalRayCount - 1);//计算间距
verticalRaySpacing = bounds.size.x / (verticalRayCount - 1);
}
private void VerticalCollisions(ref Vector3 velocity){//竖直方向的射线检测
float directionY = Mathf.Sign (velocity.y);//通过y来判断是跳跃还是下落
float rayLength = Mathf.Abs (velocity.y)+skillWidth;//射线的长度
for (int i = 0; i < verticalRayCount; i++) {
Vector2 rayOrigin = (directionY == -1) ? raycastOrigins.bottomLeft : raycastOrigins.topLeft;//通过方向来选择射线的起点
rayOrigin += Vector2.right * (verticalRaySpacing * i + velocity.x);//加上x方向的偏移
RaycastHit2D hit = Physics2D.Raycast (rayOrigin,Vector2.up*directionY,rayLength,collisionMask);//检测碰撞
Debug.DrawRay (rayOrigin,Vector2.up*directionY*rayLength,Color.red);
if (hit) {//如果发生碰撞
velocity.y = (hit.distance-skillWidth)*directionY;//移动距离变为碰撞点距物体的距离
rayLength = hit.distance;
if (collisions.climbing) {
velocity.x = velocity.y / Mathf.Tan (collisions.slopeAngle * Mathf.Deg2Rad) * Mathf.Sign (velocity.x);//当物体在斜坡上上方有障碍物时,限定x的分量
}
collisions.below = directionY == -1;
collisions.above = directionY == 1;
}
}
}
private void HorizontalCollisions(ref Vector3 velocity){//水平方向检测碰撞
float directionX = Mathf.Sign (velocity.x);//通过y来判断是跳跃还是下落
float rayLength = Mathf.Abs (velocity.x)+skillWidth;//射线的长度
for (int i = 0; i < horizontalRayCount; i++) {
Vector2 rayOrigin = (directionX == -1) ? raycastOrigins.bottomLeft : raycastOrigins.bottomRight;//通过方向来选择射线的起点
rayOrigin += Vector2.up * (horizontalRaySpacing * i);//
RaycastHit2D hit = Physics2D.Raycast (rayOrigin,Vector2.right*directionX,rayLength,collisionMask);//检测碰撞
Debug.DrawRay (rayOrigin,Vector2.right*directionX*rayLength,Color.red);
if (hit) {//如果发生碰撞
float slopeAngle = Vector2.Angle(hit.normal,Vector2.up);//得到倾斜角
if (i == 0 && slopeAngle <= maxClimbAngle) {//只判断源点的射线,如果斜坡角度小于规定的值则处于爬坡
float distanceToSlopeStart = 0;
if (slopeAngle != collisions.slopeAngleOld) {//判断是否走的同一个坡
distanceToSlopeStart = hit.distance - skillWidth;
velocity.x -= distanceToSlopeStart * directionX;//变换不同斜面时把碰撞点到物体的距离的x分量先减去
}
ClimbSlope (ref velocity, slopeAngle);//爬坡
velocity.x += distanceToSlopeStart * directionX;//处理完斜面分量在把之前的加上
}
if (!collisions.climbing || slopeAngle > maxClimbAngle) {
velocity.x = (hit.distance - skillWidth) * directionX;//移动距离变为碰撞点距物体的距离
rayLength = hit.distance;
if (collisions.climbing) {
velocity.y = Mathf.Tan (collisions.slopeAngle * Mathf.Deg2Rad) * Mathf.Abs (velocity.x);//如果物体在斜坡上水平方向遇到障碍物,则限定y分量
}
collisions.left = directionX == -1;
collisions.right = directionX == 1;
}
}
}
}
//上斜坡检测
private void ClimbSlope(ref Vector3 velocity,float slopeAngle){
float moveDistance = Mathf.Abs (velocity.x);//得到移动距离
float climbVelocityY = Mathf.Sin (slopeAngle * Mathf.Deg2Rad) * moveDistance;//得到竖直方向的分量
if (velocity.y <= climbVelocityY) {//大于时处于跳跃中不做分量
velocity.y = climbVelocityY;
velocity.x = Mathf.Cos (slopeAngle * Mathf.Deg2Rad) * moveDistance*Mathf.Sign(velocity.x);//得到水平方向的分量
collisions.below = true;//走斜坡也是地面
collisions.climbing = true;//处于斜坡上
collisions.slopeAngle = slopeAngle;
}
}
public void Move(Vector3 velocity){//移动
UpdateRaycastOrigins ();//更新射线源点
collisions.ReSet();//重置碰撞位置信息
if(velocity.x!=0)
HorizontalCollisions(ref velocity);
if(velocity.y!=0)
VerticalCollisions (ref velocity);//竖直方向检测碰撞
transform.Translate (velocity);//移动
}
struct RaycastOrigins{//射线源点
public Vector2 topLeft,topRight;
public Vector2 bottomLeft,bottomRight;
}
public struct CollisionInfo{//碰撞位置变量
public bool above,below;
public bool left,right;
public bool climbing;
public float slopeAngle, slopeAngleOld;
public void ReSet(){
above = below = false;
left = right = false;
climbing = false;
slopeAngleOld = slopeAngle;
slopeAngle = 0;
}
}
}
相比于第一部分又多了些代码,我们同样画几个图帮助理解
这里说一下,上坡认为是特殊的水平移动,只不过有了y方向的分量,所以velocity.x=s,之后velocity.x,velocity.y都根据角度得出
这里的问题是在爬坡时上方出现障碍物,如果不做处理,那么物体将照着途中的箭头循环移动。原因就是y方向受到了阻挡导致y的分量进行了限制,但是x分量正常,移动后x方向的射线进入到了斜坡内部此时被认为是水平方向的阻挡,所以会往相反方向退。代码中我们在竖直方向检测是加入了是否在爬坡,如果是在根据当前的y去限定x
有了上面的那个图,这个就好理解了。这个就是在爬坡时物体前面遇到障碍物,x为限制了,所以通过现在的x去计算y。斜坡在另一边是跟上面的一样就是方向变了,所以就不解释了。
第三部分:处理下坡,优化
这部分Player脚本没有变动
using UnityEngine;
using System.Collections;
[RequireComponent(typeof(BoxCollider2D))]
public class Controller2D : MonoBehaviour {
public LayerMask collisionMask;//射线碰撞检测层
public CollisionInfo collisions;//记录玩家处于什么位置
public int horizontalRayCount = 4;//水平方向的射线数
public int verticalRayCount = 4;//竖直方向的射线数
public float maxClimbAngle = 80f;//可以行走的斜坡最大倾斜度
public float maxDescendAngle = 80f;//下坡最大角度
private float horizontalRaySpacing;//水平方向的射线间距
private float verticalRaySpacing;//竖直方向的射线间距
private const float skillWidth = .015f;
private BoxCollider2D collider;
private RaycastOrigins raycastOrigins;
void Start(){
collider = GetComponent<BoxCollider2D> ();
CalculateRaySpacing ();
}
private void UpdateRaycastOrigins(){
Bounds bounds = collider.bounds;
bounds.Expand (skillWidth*-2);
raycastOrigins.bottomLeft = new Vector2 (bounds.min.x,bounds.min.y);
raycastOrigins.bottomRight = new Vector2 (bounds.max.x,bounds.min.y);
raycastOrigins.topLeft = new Vector2 (bounds.min.x,bounds.max.y);
raycastOrigins.topRight = new Vector2 (bounds.max.x,bounds.max.y);
}
private void CalculateRaySpacing(){//计算水平和竖直的射线间距
Bounds bounds = collider.bounds;
bounds.Expand (skillWidth*-2);//缩小包围盒
horizontalRayCount = Mathf.Clamp (horizontalRayCount,2,int.MaxValue);//限定射线数量
verticalRayCount = Mathf.Clamp (verticalRayCount,2,int.MaxValue);
horizontalRaySpacing = bounds.size.y / (horizontalRayCount - 1);//计算间距
verticalRaySpacing = bounds.size.x / (verticalRayCount - 1);
}
private void VerticalCollisions(ref Vector3 velocity){//竖直方向的射线检测
float directionY = Mathf.Sign (velocity.y);//通过y来判断是跳跃还是下落
float rayLength = Mathf.Abs (velocity.y)+skillWidth;//射线的长度
for (int i = 0; i < verticalRayCount; i++) {
Vector2 rayOrigin = (directionY == -1) ? raycastOrigins.bottomLeft : raycastOrigins.topLeft;//通过方向来选择射线的起点
rayOrigin += Vector2.right * (verticalRaySpacing * i + velocity.x);//加上x方向的偏移
RaycastHit2D hit = Physics2D.Raycast (rayOrigin,Vector2.up*directionY,rayLength,collisionMask);//检测碰撞
Debug.DrawRay (rayOrigin,Vector2.up*directionY*rayLength,Color.red);
if (hit) {//如果发生碰撞
velocity.y = (hit.distance-skillWidth)*directionY;//移动距离变为碰撞点距物体的距离
rayLength = hit.distance;
if (collisions.climbing) {
velocity.x = velocity.y / Mathf.Tan (collisions.slopeAngle * Mathf.Deg2Rad) * Mathf.Sign (velocity.x);//当物体在斜坡上上方有障碍物时,限定x的分量
}
collisions.below = directionY == -1;
collisions.above = directionY == 1;
}
if (collisions.climbing) {//平滑处理,防止移动太快而直接到另一个斜面上
float directionX = Mathf.Sign(velocity.x);
rayLength = Mathf.Abs (velocity.x)+skillWidth;
Vector2 rayOrigin1 = ((directionX==-1)?raycastOrigins.bottomLeft:raycastOrigins.bottomRight)+Vector2.up*velocity.y;
RaycastHit2D hit1 = Physics2D.Raycast (rayOrigin1,Vector2.right*directionX,rayLength,collisionMask);
if (hit1) {
float slopeAngle = Vector2.Angle (hit1.normal,Vector2.up);
if (slopeAngle != collisions.slopeAngle) {
velocity.x = (hit1.distance - skillWidth) * directionX;
collisions.slopeAngle = slopeAngle;
}
}
}
}
}
private void HorizontalCollisions(ref Vector3 velocity){//水平方向检测碰撞
float directionX = Mathf.Sign (velocity.x);//通过y来判断是跳跃还是下落
float rayLength = Mathf.Abs (velocity.x)+skillWidth;//射线的长度
for (int i = 0; i < horizontalRayCount; i++) {
Vector2 rayOrigin = (directionX == -1) ? raycastOrigins.bottomLeft : raycastOrigins.bottomRight;//通过方向来选择射线的起点
rayOrigin += Vector2.up * (horizontalRaySpacing * i);//
RaycastHit2D hit = Physics2D.Raycast (rayOrigin,Vector2.right*directionX,rayLength,collisionMask);//检测碰撞
Debug.DrawRay (rayOrigin,Vector2.right*directionX*rayLength,Color.red);
if (hit) {//如果发生碰撞
float slopeAngle = Vector2.Angle(hit.normal,Vector2.up);//得到倾斜角
if (i == 0 && slopeAngle <= maxClimbAngle) {
if (collisions.descendingSlope) {
collisions.descendingSlope = false;
velocity = collisions.velocityOld;
}
float distanceToSlopeStart = 0;
if (slopeAngle != collisions.slopeAngleOld) {
distanceToSlopeStart = hit.distance - skillWidth;
velocity.x -= distanceToSlopeStart * directionX;//变换不同斜面时把碰撞点到物体的距离的x分量先减去
}
ClimbSlope (ref velocity, slopeAngle);
velocity.x += distanceToSlopeStart * directionX;//处理完斜面分量在把之前的加上
}
if (!collisions.climbing || slopeAngle > maxClimbAngle) {
velocity.x = (hit.distance - skillWidth) * directionX;//移动距离变为碰撞点距物体的距离
rayLength = hit.distance;
if (collisions.climbing) {
velocity.y = Mathf.Tan (collisions.slopeAngle * Mathf.Deg2Rad) * Mathf.Abs (velocity.x);//如果物体在斜坡上水平方向遇到障碍物,则限定y分量
}
collisions.left = directionX == -1;
collisions.right = directionX == 1;
}
}
}
}
//上斜坡检测
private void ClimbSlope(ref Vector3 velocity,float slopeAngle){
float moveDistance = Mathf.Abs (velocity.x);//得到移动距离
float climbVelocityY = Mathf.Sin (slopeAngle * Mathf.Deg2Rad) * moveDistance;//得到竖直方向的分量
if (velocity.y <= climbVelocityY) {//大于时处于跳跃中不做分量
velocity.y = climbVelocityY;
velocity.x = Mathf.Cos (slopeAngle * Mathf.Deg2Rad) * moveDistance*Mathf.Sign(velocity.x);//得到水平方向的分量
collisions.below = true;//走斜坡也是地面
collisions.climbing = true;//处于斜坡上
collisions.slopeAngle = slopeAngle;
}
}
//下斜坡检测
private void DescendSlope(ref Vector3 velocity){
float directionX = Mathf.Sign (velocity.x);//x为正数则为1,反之为-1
Vector2 rayOrigin = (directionX == -1) ? raycastOrigins.bottomRight : raycastOrigins.bottomLeft;//射线源点根据x方向得出
RaycastHit2D hit = Physics2D.Raycast (rayOrigin,-Vector2.up,Mathf.Infinity,collisionMask);
if (hit) {
float slopeAngle = Vector2.Angle (hit.normal,Vector2.up);
if (slopeAngle != 0 && slopeAngle <= maxDescendAngle) {
if (Mathf.Sign (hit.normal.x) == directionX) {
if (hit.distance - skillWidth <= Mathf.Tan (slopeAngle * Mathf.Deg2Rad) * Mathf.Abs (velocity.x)) {//判断物体不是在空中(跳跃中)
float moveDistance = Mathf.Abs (velocity.x);
float descendVelocityY = Mathf.Sin (slopeAngle * Mathf.Deg2Rad) * moveDistance;
velocity.x = Mathf.Cos (slopeAngle*Mathf.Deg2Rad)*moveDistance*Mathf.Sign(velocity.x);
velocity.y -= descendVelocityY;//注意这里为什么是减,因为你是要下坡
collisions.slopeAngle = slopeAngle;
collisions.descendingSlope = true;
collisions.below = true;
}
}
}
}
}
public void Move(Vector3 velocity){//移动
UpdateRaycastOrigins ();//更新射线源点
collisions.ReSet();//重置碰撞位置信息
collisions.velocityOld = velocity;//每次移动时把速度记下来
if(velocity.y<0)
DescendSlope(ref velocity);//下坡检测
if(velocity.x!=0)
HorizontalCollisions(ref velocity);
if(velocity.y!=0)
VerticalCollisions (ref velocity);//竖直方向检测碰撞
transform.Translate (velocity);//移动
}
struct RaycastOrigins{//射线源点
public Vector2 topLeft,topRight;
public Vector2 bottomLeft,bottomRight;
}
public struct CollisionInfo{//碰撞位置变量
public bool above,below;
public bool left,right;
public bool climbing;
public float slopeAngle, slopeAngleOld;
public bool descendingSlope;//处于下坡
public Vector3 velocityOld;
public void ReSet(){
above = below = false;
left = right = false;
climbing = false;
slopeAngleOld = slopeAngle;
slopeAngle = 0;
descendingSlope = false;
}
}
}