Unity 3D部分
3D 坐标系
2D坐标
- 只考虑 XY 坐标
屏幕坐标
- 左下(0,0)类似一个象限
3D坐标(世界坐标)
- XYZ 坐标
3D物理系统:刚体
类似2D刚体
3D物理系统:碰撞体
类似2D碰撞体
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class L6_3Demo : MonoBehaviour
{
// 碰撞进入
private void OnCollisionEnter(Collision collision)
{
Debug.Log(collision.gameObject.name);
}
// 碰撞中
private void OnCollisionStay(Collision collision)
{
Debug.Log(collision.gameObject.name);
}
// 碰撞退出
private void OnCollisionExit(Collision collision)
{
Debug.Log(collision.gameObject.name);
}
}
3D物理系统:触发
类似2D触发
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class L6_4Demo : MonoBehaviour
{
// Enter
private void OnTriggerEnter(Collider other)
{
print("Enter: " + other.gameObject.name);
}
// Stay
private void OnTriggerStay(Collider other)
{
print("Stay: " + other.gameObject.name);
}
// Exit
private void OnTriggerExit(Collider other)
{
print("Exit: " + other.gameObject.name);
}
}
3D物理系统:物理材质
类似2D物理材质
物理射线
用于判断射击是否命中、点击地面建造建筑物等功能
Ray:射线类
Physics.Raycast:计算射线碰撞
RaycastHit:射线检测信息类
Debug.DrawLine:绘制线条(玩家看不到,仅编辑器测试)
演示:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class L6_6Demo : MonoBehaviour
{
void Update()
{
// 射线, 向上, 从 0 0 0 到 0 1 0
//Ray ray = new Ray(Vector3.zero,new Vector3(0,1,0));
// 类似射击游戏的实现
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray,out RaycastHit hitinfo,1000))
{
// hitinfo: 射线碰撞的相关信息
Debug.Log(string.Format("Rayline hit: {0}, Where: {1}", hitinfo.collider.gameObject.name,hitinfo.point));
Debug.DrawLine(ray.origin, hitinfo.point,Color.red);
}
}
}
刚体移动
Rigidbody.MovePosition(Vector3 target)
:target 是一个具体要到达的位置
演示:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class L6_7Demo : MonoBehaviour
{
private Rigidbody rb;
void Start()
{
rb = GetComponent<Rigidbody>();
}
// 帧率更新
void Update()
{
}
//固定更新
void FixedUpdate()
{
Move();
}
private void Move()
{
// 获取输入
float h = Input.GetAxis("Horizontal");
float v = Input.GetAxis("Vertical");
Vector3 offset = new Vector3(h, 0, v) * Time.deltaTime * 1.5f;
rb.MovePosition(transform.position + offset);
}
}
案例:方块保卫战
| 场景搭建
介绍
敌人向玩家走来
玩家点击屏幕可以发射子弹
子弹击中敌人两次则敌人死亡销毁
敌人如果到达指定位置,则玩家失败,进行重新游玩
分析
搭建基本场景和敌人外观
实现敌人自动移动
实现玩家发射子弹逻辑
- UI 显示当前得分
游戏结果,需要 UI 弹窗提醒结果
击毙全部敌人胜利
敌人进入指定位置触发失败
搭建
| 核心逻辑
实现敌人自动移动
实现玩家攻击敌人
敌人死亡逻辑
游戏胜利逻辑
游戏失败逻辑
| UI逻辑
UI 显示当前得分
游戏结果面板(胜利与失败)
代码部分:
L6_8_Enemy
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class L6_8_Enemy : MonoBehaviour
{
private Rigidbody rb;
private float speed = 2;
private int hp = 100;
void Start()
{
rb = GetComponent<Rigidbody>();
}
private void FixedUpdate()
{
Move();
}
private void Move()
{
Vector3 offset = transform.forward * Time.fixedDeltaTime * speed;
rb.MovePosition(transform.position + offset);
}
public void Hurt(int demage)
{
hp -= demage;
if (hp <= 0)
{
Dead();
}
}
private void Dead()
{
// check 还有没有同类,如果没有,则游戏胜利
L6_8_Player.Instance.EnemyDead(this);
// die
Destroy(gameObject);
}
}
L6_8_Player
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class L6_8_Player : MonoBehaviour
{
public static L6_8_Player Instance;
private int AttackValue = 50;
public List<L6_8_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, 1000))
{
Debug.DrawLine(ray.origin, hitinfo.point, Color.red);
// 如果我射击到的是敌人,则附加伤害
if (hitinfo.collider.gameObject.tag == "Enemy")
{
// 附加伤害
L6_8_Enemy enemy = hitinfo.collider.gameObject.GetComponent<L6_8_Enemy>();
enemy.Hurt(AttackValue);
}
}
}
}
public void EnemyDead(L6_8_Enemy enemy)
{
score += 1;
L6_8_UIManager.Instance.UpdateScoreNumText(score);
enemies.Remove(enemy);
if(enemies.Count == 0)
{
// victory
Win();
}
}
private void Win()
{
L6_8_UIManager.Instance.GameResult(true);
}
private void Over()
{
isOver = true;
//Time.timeScale = 0;
L6_8_UIManager.Instance.GameResult(false);
}
private void OnTriggerEnter(Collider other)
{
if (other.gameObject.tag == "Enemy" && isOver == false)
{
Over();
}
}
}
L6_8_UIManager
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class L6_8_UIManager : MonoBehaviour
{
public static L6_8_UIManager Instance;
public Text ScoreNumText;
public GameObject resultPanel;
public Text resultText;
private void Awake()
{
Instance = this;
}
public void UpdateScoreNumText(int num)
{
ScoreNumText.text = num.ToString();
}
public void GameResult(bool isWin)
{
resultPanel.SetActive(true);
if (isWin)
{
resultText.text = "Victory";
}
else
{
resultText.text = "Defeat";
}
}
}