unity自带的2D刚体在坡上会往下滑。而且也是会有可能穿墙,或碰撞到其他物体时鬼畜抖动。

设计思路

1、利用射线进行判断碰撞防止穿墙:

原理传送门

2、在地面时往地面发射两条射线,获得的两个点,两个点形成的线,这个线是角色的移动向量。

下面是一个自定义的一个横板2D角色控制器,包含有简单的移动和跳跃。

代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class CharacterController2D : MonoBehaviour
{/// <summary>/// 角色输入轴/// </summary>public Vector2 axis;/// <summary>/// 角色受到的重力/// </summary>public float gravity = 10;/// <summary>/// 角色的移动速度/// </summary>public float moveSpeed = 30;/// <summary>/// 角色跳跃力/// </summary>public float jumpForce;/// <summary>/// 中心点偏移/// </summary>public Vector3 offset;/// <summary>/// 最大速度向量/// </summary>public float maxSpeed = 100;/// <summary>/// 前长度:该值决定角色到前墙的碰撞距离/// </summary>public float forwardLength = 1;/// <summary>/// 底长度:该值决定角色到地面的距离/// </summary>public float bottonLnegth = 0.5f;/// <summary>/// 底下的先与旁边的线偏移距离/// </summary>public float bottonForwardOffset = 0.25f;/// <summary>/// 上一次跳跃的到现在时间/// </summary>public float JumpTime { get => jumpTime; }/// <summary>/// 返回X轴的绝对值/// </summary>public float AxisAbs { get => axisAbs; }/// <summary>/// 角色是否进行了X反转/// </summary>public bool ReversalX { get => reversalX; }/// <summary>/// 角色是否在地面/// </summary>public bool OnGround { get => onGround; }/// <summary>/// 角色的实际位移速度/// </summary>public Vector3 Velocity { get => velocity; }/// <summary>/// 获取射线起始点/// </summary>public Vector3 RaycastStartPosi { get { return transform.position + offset; } }/// <summary>/// 获取X的速度长度(Mathf.Abs(velocity.x) * Time.deltaTime;)/// </summary>public float SpeedLengthX { get { return Mathf.Abs(velocity.x) * Time.deltaTime; } }/// <summary>/// 获取Y的速度长度(Mathf.Abs(velocity.y) * Time.deltaTime;)/// </summary>public float SpeedLengthY { get { return Mathf.Abs(velocity.y) * Time.deltaTime; } }/// <summary>/// 是否打开前方检测/// </summary>public bool OpenForward { get => openForward; set => openForward = value; }/// <summary>/// 是否打开自由浮空/// </summary>public bool FreeFloating { get => freeFloating; set => freeFloating = value; }/// <summary>/// 获取角色前面/// </summary>public Vector3 Forward{get{Vector3 forward = transform.right;forward.x = ReversalX ? forward.x * -1 : forward.x;return forward;}}private bool reversalX;private float axisAbs;private bool onGround;private float jumpTime;private bool openForward = true;private bool freeFloating = true;private Vector3 velocity;private Transform downJumpPlatform;/// <summary>/// 绘制碰撞检测距离/// </summary>private void OnDrawGizmos(){//fDebug.DrawRay(RaycastStartPosi, Forward * forwardLength, Color.green);//bVector3 forward = RaycastStartPosi + Forward * bottonForwardOffset;Debug.DrawRay(RaycastStartPosi, Vector2.down * bottonLnegth, Color.green);Debug.DrawRay(forward, Vector2.down * bottonLnegth, Color.green);//tDebug.DrawRay(RaycastStartPosi, Vector2.up * bottonLnegth, Color.green);}void Update(){if (axis.x < 0){reversalX = true;}else if (axis.x > 0){reversalX = false;}jumpTime += Time.deltaTime;axisAbs = Mathf.Abs(axis.x);//刷新角色的速度VelocityUpdate();velocity = Vector3.ClampMagnitude(velocity, maxSpeed);transform.position += velocity * Time.deltaTime;}/// <summary>/// 跳跃/// </summary>public void Jump(){if (OnGround){onGround = false;jumpTime = 0;RaycastHit2D bottonHit = Physics2D.Raycast(RaycastStartPosi, Vector2.down, bottonLnegth + SpeedLengthY, LayerMask.GetMask("Ground"));if (bottonHit && bottonHit.transform.tag == "Plane" && axis.y < 0){downJumpPlatform = bottonHit.transform;}else{velocity.y = jumpForce;}}}private void VelocityUpdate(){RaycastHit2D bottonHit, forwardHit;GetBottonRaycastHit(out bottonHit, out forwardHit);if (jumpTime > 0.2 && bottonHit && forwardHit){//如果是在平台上,并且下跳平台不为空if (downJumpPlatform){if (downJumpPlatform != bottonHit.transform){downJumpPlatform = null;}}else{onGround = true;//速度方向Vector2 speedDirection = (forwardHit.point - bottonHit.point).normalized;//坡度检查if (Vector3.Dot(speedDirection, Vector2.up) < 0.6f){velocity = speedDirection * AxisAbs * moveSpeed;}velocity.y = 0;transform.position = new Vector3(transform.position.x,(bottonHit.point.y <= forwardHit.point.y ? bottonHit.point.y : forwardHit.point.y) + bottonLnegth - bottonLnegth*0.1f - offset.y,transform.position.z);}}//在空中时else{onGround = false;if (freeFloating){velocity.x = axis.x * moveSpeed;}velocity.y -= gravity * Time.deltaTime;}RaycastHit2D topHit = Physics2D.Raycast(RaycastStartPosi, Vector2.up, bottonLnegth + SpeedLengthY, LayerMask.GetMask("Ground"));//如果顶部撞到墙并没撞到、或撞到的不是平台if (!topHit || topHit.transform.tag != "Plane"){if (topHit){velocity.y = 0;}FudgeForward();}}private void FudgeForward(){if (openForward){//判断是否撞墙XRaycastHit2D rf = GetForwardHit();if (rf){velocity.x = 0;float x = reversalX ? forwardLength - 0.1f : -forwardLength + 0.1f;transform.position = new Vector3(rf.point.x + x - offset.x,transform.position.y,transform.position.z);}}}private void GetBottonRaycastHit(out RaycastHit2D bottonHit, out RaycastHit2D forwardHit){//前射线位置Vector3 forward = RaycastStartPosi + Forward * bottonForwardOffset;//发射射线bottonHit = Physics2D.Raycast(RaycastStartPosi, Vector2.down, bottonLnegth + SpeedLengthY, LayerMask.GetMask("Ground"));forwardHit = Physics2D.Raycast(forward, Vector2.down, bottonLnegth + SpeedLengthY, LayerMask.GetMask("Ground"));}public RaycastHit2D GetForwardHit(){RaycastHit2D rf = Physics2D.Raycast(RaycastStartPosi, Forward, forwardLength + SpeedLengthX, LayerMask.GetMask("Ground"));return rf;}
}

end

Unity 2D角色控制器(横板滚轴)相关推荐

  1. Unity 2D动画控制器详解

    http://www.tairan.com/archives/6939#16 文章目录 开始 过渡 编辑过渡 颜色变化 动画参数 复习一下 CatConga动画 CatDisappear Clip A ...

  2. unity 2d角色移动卡住的原因

    unity 2d角色移动时卡住原地踏步的原因 可能是碰撞盒子是正方形 被地图的碰撞体卡住的原因 应该把脚底做成圆形的碰撞盒 防止和地面的碰撞盒子卡住

  3. Unity自定义角色控制器(一):碰撞检测

    我实在很喜欢用Unity.它在处理很多底层问题的同时有给了开发者很多自由.而且它还有着非常活跃的社区,起到了很大的帮助. 不幸的是,之前也说了,Unity也带着世界上最糟糕的角色控制器.在与Unity ...

  4. untiy 2D角色控制器

    这节讲讲类似马里奥,盗贼遗产,这些类似的游戏人物基本的控制方式.这里我用Prime31这个公司的插件改了一个比较小的控制脚本,博客结尾会给大家一份源码,先简单的讲一下2D人物控制器的原理,2D控制器可 ...

  5. Unity超级角色控制器研究(四)——地形检测

    一个地形检测反例 因此我们想知道什么在角色脚底下呢?首先是距离脚下有多远.我们会想知道角色的脚是否贴着地面还是在半空中.我们还会想知道脚下地面具体位置坐标,这对于上一章强调过的钳住地面是很重要的.第三 ...

  6. Unity:角色控制器(CharacterController)

    角色控制器是unity中专门用来控制角色的组件(主要是运动相关),区别于直接用Transform或者RigidBody,CharacterController有着更好的效果,它拥有RigidBody的 ...

  7. unity 使用角色控制器CharacterController移动对象造成模型动画的抖动

    使用角色控制器控制对象的移动,主要用到Move和simplemove函数: function Move (motion : Vector3)   //montion表示将控制器移动到这个坐标点,注意它 ...

  8. Unity 2D角色动画状态切换

    一,Idle状态 1,选中角色,打开Animation动画面板: 2,新建一个动画面板Idle; 3,拖动相关角色状态图片,实现动画 二,run状态 1,新建一个动画面板run; 2,拖动相关角色状态 ...

  9. unity 2d 角色顺畅的移动+跳跃+动画切换

    参考:https://www.bilibili.com/video/av82865782?t=818 直接贴代码 playerController.cs using System.Collection ...

最新文章

  1. 循环斐波那契数列_剑指offer #10 斐波那契数列
  2. 针对淡入淡出的定时轮播效果js
  3. Windows环境配置Anaconda+cuda+cuDNN+pytorch+jupyter notebook
  4. 子集—leetcode78
  5. Codeforces Round #762 (Div. 3)
  6. oracle之单行函数之子查询
  7. Linux基础(iptables与firewalld防火墙)
  8. java怎么快速创建监听类_如何创建监听器
  9. conda deactivate python3_conda进行python环境隔离
  10. C_C++编程题:选择填空、智力题
  11. iPlayer惨遭破解诅咒AKAIO作者扬言要让它支持商业游戏
  12. jsp中向数据库中插入当前时间的方法精确到秒
  13. 变身mac达人,这几招技巧您有必要了解~
  14. 零样本学习的相关概念——综述
  15. 极客大学产品经理训练营:数据分析与用户数据 第17课总结
  16. verilog REG 寄存器、向量、整数、实数、时间寄存器
  17. 前端技巧总结---持续更新
  18. 2021年美赛解题思路汇总Final!!!
  19. 通读《构建之法》之后的问题
  20. SpringCloud - LCN分布式事务框架

热门文章

  1. 【Matlab】极小值原理
  2. 美科技巨头每秒能赚多少钱?苹果11376元、谷歌6691元
  3. java long加减_java 日期加减
  4. Apache和PHP结合
  5. CRect 详解及注意事项
  6. 开源Web漏洞扫描工具–Arachni
  7. 黑群晖 WebDAV Server 通过 NetDriver2 连接报错 Permission Error
  8. 20行Python代码,无损压缩千百张图片!
  9. 2018年全球邮件客户端市场份额及发展趋势
  10. Exception in thread main com.alibaba.fastjson.JSONException: create asm serializer error