请查看(2D)物理专栏 http://t.csdnimg.cn/rDJTo
1.人物刚体和碰撞器
Q:瓦片地图和碰撞体不贴合怎么办?
A:在该瓦片图集的精灵编辑器里面找到自定义物理形状后,将边缘容忍度设置高一些生成或者自定义点,做到尽量贴合
2.瓦片地图复合碰撞器
3.输入配置文件
新输入系统请查看输入模块:
为Player创建一个脚本和添加一个Player Input,创建默认InputActions(输入配置文件)我就叫PIC吧,生成C#代码
并且建议使用第三或者第四种监听方式,比较直观和方便
4.人物移动
可以用刚体加力,刚体速度,也可以用transform的直接移动,这块属于必会的基础部分,我没有写博客,所以干脆分别演示一下
Translate
private PIC pic;
public Vector2 wasdValue;
//设置移动速度
public float playerSpeed=50;
private void OnEnable() {
pic = new PIC();
pic.Enable();
}
private void OnDisable() {
pic.Disable();
}
private void Update() {
wasdValue = pic.Player.Move.ReadValue<Vector2>();
this.transform.Translate(playerSpeed* wasdValue*Time.deltaTime);
}
缺点也很明显,不符合物理特性,上下左右乱飞
刚体加力
private PIC pic;
public Vector2 wasdValue;
//设置移动速度
public float playerSpeed;
//获取刚体组件
private Rigidbody2D rb ;
private void Awake() {
playerSpeed = 20;
rb = GetComponent<Rigidbody2D>();
pic = new PIC();
}
private void OnEnable() {
pic.Enable();
}
private void OnDisable() {
pic.Disable();
}
private void Update() {
wasdValue = pic.Player.Move.ReadValue<Vector2>();
}
private void FixedUpdate() {
rb.AddForce(wasdValue*Time.deltaTime,ForceMode2D.Impulse);
}
额,刚体加力默认是以轴心点加力的,所以会造成旋转,因此要锁住z轴
刚体速度
private PIC pic;
public Vector2 wasdValue;
//设置移动速度
public float playerSpeed;
//获取刚体组件
private Rigidbody2D rb ;
private void Awake() {
playerSpeed = 20;
rb = GetComponent<Rigidbody2D>();
pic = new PIC();
}
private void OnEnable() {
pic.Enable();
}
private void OnDisable() {
pic.Disable();
}
private void Update() {
wasdValue = pic.Player.Move.ReadValue<Vector2>();
}
private void FixedUpdate() {
rb.velocity= new Vector2(wasdValue.x*Time.deltaTime* playerSpeed,rb.velocity.y);
}
5.人物翻转
人物翻转有两种方法,用tansformscale或者sprite renderer的flip功能(我关于精灵渲染器的部分没有写这个小知识点,再次体会到了任何一处细节都有可能用得上)
tansformscale(要求pivot在人物左右的分割线上)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
public class PlayerControl : MonoBehaviour
{
private PIC pic;
public Vector2 wasdValue;
//设置移动速度
public float playerSpeed;
//获取刚体组件
private Rigidbody2D rb ;
private void Awake() {
playerSpeed = 200;
rb = GetComponent<Rigidbody2D>();
pic = new PIC();
}
#region 启用和禁用
private void OnEnable() {
pic.Enable();
}
private void OnDisable() {
pic.Disable();
}
#endregion
private void Update() {
wasdValue = pic.Player.Move.ReadValue<Vector2>();
//注意,不能直接修改transform xyz中的其中一个值
Vector3 flip = this.transform.localScale;
//翻转逻辑
if (wasdValue.x > 0)
{ flip.x = wasdValue.x;
this.transform.localScale = flip; }
if (wasdValue.x < 0)
{ flip.x = wasdValue.x;
this.transform.localScale = flip; }
}
private void FixedUpdate() {
//加力逻辑
rb.velocity= new Vector2(wasdValue.x*Time.deltaTime* playerSpeed,rb.velocity.y);
}
}
Sprite Renderer Flip(建议)
这样只需要两行逻辑就可以了,建议用这种方法
//翻转逻辑
if (wasdValue.x > 0)
{
spriteRenderer.flipX = false;
}
if (wasdValue.x < 0)
{
spriteRenderer.flipX = true;
}
6.订阅跳跃事件
这还是不得不提到新输入系统,请查看本文第三个标题中链接专栏的内容
配置一下Action
我直接用lambda表达式 来订阅事件,因为没有太多复杂的输入的话,不必重用代码这样也会比较清晰:C# 匿名函数与Lambda表达式-CSDN博客
注意参数,这实际上是使用的playerinput的第四种监听方式
private void Update() {
wasdValue = pic.Player.Move.ReadValue<Vector2>();
pic.Player.Jump.started += (context) => {
rb.AddForce(this.transform.up * jumpSpeed,ForceMode2D.Impulse);
};
但是,这样可能存在不断订阅事件从而影响性能地问题
所以可以在disenble中添加一行,以移除所有回调函数
pic.Player.Jump.RemoveAction();
7.连跳和分层检测
这一块和射线检测有关,重点在于物理组件中的检测方法,你可以在我链接中最后一部分找到它unity保姆级教程之 射线检测_unity 射线-CSDN博客
因为游戏中多物品的交互会比较复杂,所以要分层级去判断不同的影响方式,你也不想水和地面一样硬吧!
有些案例会通过api让你手搓一个简单的分层检测方法,这里我就直接和麦扣写一样了,这样比较方便,也有利于后续拓展
注意我设置了偏移量,因为我裁剪图集的时候中心点在center而不是botton
using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;
public class PhysicsCheck : MonoBehaviour
{
//地面检测
public bool isGround;
//检测半径
public float raduis;
//检测层级
public LayerMask ground;
//检测偏移量
public Vector2 positionWithOffset;
private void Start() {
raduis = 0.3f;
}
private void Update() {
Check();
}
private void Check()
{
positionWithOffset = new Vector2(this.transform.position.x-0.2f, this.transform.position.y - 1.0f);
isGround = Physics2D.OverlapCircle(positionWithOffset, raduis, ground);
}
private void OnDrawGizmosSelected() {
Gizmos.DrawWireSphere(positionWithOffset, raduis);
}
}
还有一个问题就是连跳,用isground判断就行了
pic.Player.Jump.started += (context) => {
if(physicsCheck.isGround=true)
rb.AddForce(this.transform.up * jumpSpeed,ForceMode2D.Impulse);
};
画辅助线我之前没在意这个细节,所以没有在博客中提到
private void OnDrawGizmosSelected() {
Gizmos.DrawWireSphere(positionWithOffset, raduis);
}