Unity基础笔记(4)—— Unity3D部分

Unity3D部分

一、3D坐标系

1. 2D坐标、屏幕坐标、3D坐标(世界坐标)

2D游戏时我们只考虑了X、Y的坐标,但是实际上这里的X和Y就是世界坐标中对应的X、Y。

屏幕坐标以左下角为原点(0,0),右上角坐标为(width,height),width为屏幕宽度,height为屏幕高度。

(ctrl + shift + F 相机快速对焦)

二、3D物理系统

1. 刚体

与2D的刚体类似

Rigidbody 组件:

  • Is Kinematic:是否自己模拟物理效果,若是使用代码接管,可以勾上。
  • Collision Detection:碰撞检测频率

2. 碰撞体

与2D的碰撞体类似

3. 触发

与2D的触发类似

4. 物理材质

与2D的物理材质类似

  • Dynamic Friction:动态摩擦力
  • Static Friction:静态摩擦力
  • Bounciness:弹性
  • Friction Combine:当两个物体发生摩擦时,摩擦力如何计算
  • Bounce Combine:当两个物体碰撞时,弹性如何计算

三、物理射线

用于判断射击是否命中、点击地面建造建筑物等功能。

  • Ray:射线类
  • Physics Raycast:计算射线碰撞
  • RaycastHit:射线检测信息类
  • Debug.DrayLine:绘制线条(玩家无法看到,仅编辑器测试用)
void Update()
{
    // 一条向上的射线,从(0,0,0)到(0,1,0)
    Ray ray1 = new Ray(Vector3.zero, new Vector3(0, 1, 0));

    // 从屏幕中心点向鼠标位置射出的射线
    Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);

    // 从ray方向上1000米距离内的发出射线是否能碰到物体
    if (Physics.Raycast(ray, out RaycastHit hitinfo, 1000))
    {
        // hitinfo 射线碰撞的相关信息
        Debug.Log("射线碰到了物体");
        Debug.Log(string.Format("射线碰到了{0},在位置{1}", hitinfo.collider.gameObject.name, hitinfo.point));

        Debug.DrawLine(ray.origin, hitinfo.point, Color.red);

    }

}

四、刚体移动

Rigidbody.MovePosition(Vector3 target);

刚体移动语句,target 是一个具体要到达的位置。

// 固定更新
void FixedUpdate()
{
    Move();
}

private void Move()
{
    // 获取输入
    float h = Input.GetAxis("Horizontal");
    float v = Input.GetAxis("Vertical");

    Vector3 offset = new Vector3(h, 0, v) * 0.02f * 1.5f;
    rigidbody.MovePosition(transform.position + offset);

}

偏移量 offset 应该等于 要移动的方向向量 * 画面更新时间 * 实际速度。

刚体移动方法中的target 应该等于 偏移量offset + 当前位置transform.position.

五、案例:方块保卫战

1. 案例介绍

  • 敌人向玩家走来
  • 玩家点击屏幕可以发射子弹
  • 子弹击中敌人两次则敌人死亡销毁
  • 敌人如果到达指定位置,则玩家失败,进行重新游玩

2. 案例分析

  • 搭建基本场景和敌人外观
  • 实现敌人自动移动
  • 实现玩家发射子弹逻辑
    • UI 显示当前得分
  • 游戏结果,需要 UI 弹窗提醒结果
    • 击毙所有敌人胜利
    • 敌人进入指定位置触发失败

3. 场景搭建

4. 核心逻辑

  • 实现敌人自动移动
  • 实现玩家攻击敌人
  • 敌人死亡逻辑
  • 游戏胜利逻辑
  • 游戏失败逻辑

5. UI 逻辑

  • UI 显示当前得分
  • 游戏结果面板(胜利与失败)
// 玩家逻辑
public class Player : MonoBehaviour
{
    // 单例模式
    public static Player instance;
    // 攻击力
    private int AttackValue = 100;
    // 存储敌人
    public List<Enemy> enemies;
    private int score = 0;
    private bool isOver = false;

    private void Awake()
    {
        instance = this;
    }
    void Update()
    {
        Shoot();
    }

    private void Shoot()
    {
        if (Input.GetMouseButtonDown(0))
        {
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            if (Physics.Raycast(ray, out RaycastHit hitinfo, 100))
            {
                Debug.DrawLine(ray.origin, hitinfo.point, Color.red);

                // 如果我射击到的是敌人,则附加伤害
                if (hitinfo.collider.gameObject.tag == "Enemy")
                {
                    // 附加伤害
                    Enemy enemy = hitinfo.collider.gameObject.GetComponent<Enemy>();

                    enemy.Hurt(AttackValue);
                }
            }
        }
    }

    public void EnemyDead(Enemy enemy)
    {
        score += 1;
        UI_Manager.instance.UpdateScoreText(score);
        enemies.Remove(enemy);
        if (enemies.Count == 0)
        {
            // 游戏胜利
            Win();
        }
    }

    private void Win()
    {
        UI_Manager.instance.GameResult(true);
    }

    private void Over()
    {
        isOver = true;    
        UI_Manager.instance.GameResult(false);
        Time.timeScale = 0;
    }

    private void OnTriggerEnter(Collider other)
    {
        if (other.gameObject.tag == "Enemy" && isOver == false)
        {
            Over();
        }
    }
}
// 敌人逻辑
public class Enemy : MonoBehaviour
{
    private Rigidbody rbody;
    private float speed = 2.2f;
    private int HP = 100;

    void Start()
    {
        rbody = GetComponent<Rigidbody>();
    }
    private void FixedUpdate()
    {
        Move();
    }

    private void Move()
    {

        Vector3 offset = transform.forward * Time.fixedDeltaTime * speed;
        rbody.MovePosition(transform.position + offset);

    }

    public void Hurt(int damage)
    {
        HP -= damage;
        if(HP <= 0)
        {
            Dead();
        }
    }

    private void Dead()
    {
        // 检查一下,还有没有其他敌人,如果没有则玩家胜利
        Player.instance.EnemyDead(this);
        // 死亡
        Destroy(gameObject);
    }
}
// UI管理器
public class UI_Manager : MonoBehaviour
{
    public static UI_Manager instance;
    public Text ScoreText;

    public GameObject resultPanel;
    public Text resultText;

    private void Awake()
    {
        instance = this;
    }

    public void UpdateScoreText(int num)
    {
        ScoreText.text = num.ToString();
    }

    public void GameResult(bool isWin)
    {
        resultPanel.SetActive(true);
        if(isWin)
        {
            resultText.text = "胜利";
        }
        else
        {
            resultText.text = "失败";
        }
    }
}

猜你喜欢

转载自blog.csdn.net/Dukenone/article/details/126916653
今日推荐