1. はじめに
1. キャラクターのパーツ
a、キャラクターの動き
b、カメラの回転
c、プレイヤーの射撃: アニメーション、音声、列挙、銃弾の穴、倍率
2、敵のパーツ
a、敵のクローン
b、プレイヤーに向かって歩く: 距離、方向、向き、内積、外積
2.キャラクター部分
(1)、キャラクターの動き
CharacterController c;//角色控制器
Vector3 moveDirection = Vector3.zero;//移动方向
float moveSpeed = 6, jumpSpeed = 4;
float gravity = 20;
void Start()
{
c = GetComponent<CharacterController>();
}
void Update()
{
if (c.isGrounded)
{
float h = Input.GetAxis("Horizontal");
float v = Input.GetAxis("Vertical");
//固定坐标的前后左右移动
//direction = new Vector3(h, 0, v);
//第一人称移动,normalized表示长度1
moveDirection = (transform.right * h + transform.forward * v).normalized;
if (Input.GetButton("Jump"))
{
moveDirection.y = jumpSpeed;
}
}
//一直有一个重力加速度
moveDirection.y -= gravity * Time.deltaTime;
c.Move(moveDirection * moveSpeed * Time.deltaTime);
}
Move と SimpleMove について
1. SimpleMove
SimpleMove は平面上でのみ移動でき、Y 軸の移動はありません。
移動には独自の速度があります。
自重で移動する場合はTime.deltaTime を掛ける必要はありません
2. Move の移動
方向に制限はありません.
(1)の一人称移動コードだけでは不十分で、キャラクターの方向をマウスで制御して一人称移動を反映させる必要があります。
(2)、カメラの回転(キャラクターがその方向を向く、台本がキャラクターにぶら下がる)
Vector3 cameraRotate;
float rotateSpeed = 3f;
void Update () {
//获取鼠标水平和竖直方向的偏移量
float x = Input.GetAxis("Mouse X");
float y = Input.GetAxis("Mouse Y");
//左右旋转(绕Y轴旋转);
cameraRotate.x -= y * rotateSpeed;
//抬头低头(绕X轴旋转)
cameraRotate.y += x * rotateSpeed;
//抬头低头范围
cameraRotate.x = Mathf.Clamp(cameraRotate.x, -45, 45);
//左右旋转范围(CS人物是可以左右无限制旋转的,所以这里可以去掉)
//cameraRotate.y = Mathf.Clamp(cameraRotate.x,-90,90);
transform.rotation = Quaternion.Euler(cameraRotate.x, cameraRotate.y, 0);
}
動きを良くするために、マウスを非表示にすることができます
Cursor.lockState = CursorLockMode.Locked;
(3)、プレイヤーがシュート
Transform pos;//枪口位置
private GameObject explosionFx;//爆炸特效
private AudioClip explosionAudios, fireAudios;//爆炸音频,开枪音频
void Start()
{
//动态加载资源(路径: Assets/Resources/Prefabs/HitBlood)
explosionFx = Resources.Load<GameObject>("Prefabs/HitBlood");
explosionAudios = Resources.Load<AudioClip>("Audios/boom");
fireAudios = Resources.Load<AudioClip>("Audios/shoot");
}
void Update()
{
if (Input.GetButtonDown("Fire1"))
{
//点击左键,枪口位置发出开枪音频(自动消失)音量1
AudioSource.PlayClipAtPoint(fireAudios, pos.position, 1f);
RaycastHit hit;//碰撞信息
//检测射线(枪口位置,人物向前方向,碰撞信息,距离20米)
if (Physics.Raycast(pos.position, transform.forward, out hit, 20))
{
GameObject go = Instantiate(explosionFx, hit.point, Quaternion.identity);
Destroy(go, 1f);
//播放爆炸特效(自动消失),音量1
AudioSource.PlayClipAtPoint(explosionAudios, hit.point, 1f);
Destroy(hit.collider.gameObject);
}
}
}
注:
(a) cs は光線で発射する必要があります。拡大を実現する必要があるため (フロントサイトを使用して位置合わせすることはできません)、銃口ではなくカメラの中心で発射することを最終的に選択しました ( b)、射撃するときは、
銃のアニメーションが必要です
//方法:
Animation an;//动画
void Start()
{
an.GetComponent<Animation>();
}
//an.play("动画名");
an.play("Fire2");
©、オーディオ
public class ResManage
{
//该类的目的是为了存储字符串,简洁其他类
//声音路径
public const string walk = "Sounds/playWalk";//走路声音
public const string run = "Sounds/playRun";//跑步声音
}
AudioClip landClip, runClip;//音频片段
AudioSource audios;//音频组件
void Start()
{
//音频资源
audios = GetComponent<AudioSource>();
//动态加载资源,(体现ResManage类的目的)
landClip = Resources.Load<AudioClip>(ResManage.walk);
runClip = Resources.Load<AudioClip>(ResManage.run);
}
(d) エニュメレーションの応用 アニメを
再生する場合、通常はエニュメレーションで書く(敵のアニメはここに書く)
enum States
{
Idle,
Run,
Death,
Attack
};
void GetStates(States s)
{
switch (s)
{
case States.Idle:
an.Play(ResManage.nurseIdle);
break;
case States.Run:
an.Play(ResManage.nurseRun);
break;
case States.Death:
an.Play(ResManage.nurseDeath);
break;
case States.Attack:
an.Play(ResManage.nurseAttack);
break;
default:
break;
}
}
使用法: GetStates(States.Idle);
(e)、銃弾の穴の位置
if (Physics.Raycast(ray, out hit, 100))//摄像机发射
{
if (hit.collider.CompareTag("Plane"))
{
//子弹打洞
//打到地板克隆弹孔
GameObject go = Instantiate(holeEffect, hit.point, holeEffect.transform.rotation);
//让弹孔与射线碰撞体的法线垂直(让弹孔总是贴在碰撞体表面)
go.transform.LookAt(hit.point - hit.normal);
//让弹孔与碰撞体表面保持0.03距离(这里看着合适就行)
go.transform.Translate(Vector3.back * 0.03f);
Destroy(go, 1f);
}
}
(f)、倍率(減算は倍率)
camera.GetComponent().fieldOfView-=45;
3.敵パーツ
(1)、クローン敵
(ある点(x1,y1,z1)を中心に範囲1~5 m は 5 体の敵をスポーンします)
for (int i = 0; i < 5; i++)
{
float a = Random.Range(1, 5);
//从原点坐标获取任意一个方向的向量
Vector2 b = Random.insideUnitCircle;
//获取向量的单位向量
Vector2 c = b.normalized;
//得到位置
Vector3 d = new Vector3(x1 + c.x * a, y1, z1 + c.y * a);
Instantiate(enemy, d, transform.rotation);
}
(2)敵とプレイヤーの
距離:
Vector.Distance (敵の位置、プレイヤーの位置) を使用し、距離を判断してアニメーションを再生し、プレイヤーに向かって移動します。
if (Vector3.Distance(transform.position, player.transform.position) <= 10)
オリエンテーションの質問:
//敌人指向玩家方向
dir = (player.transform.position - transform.position).normalized;
質問に向かって:
transform.LookAt(player.transform.position);
(3)、敵の位置を特定し
、点数を掛ける
//点乘
float a = Vector3.Dot(transform.forward, enemy.transform.position - player.transform.position);
if (a <= 0)
{
tipWarn.text = "警告:后方发现敌人";
}
else
{
tipWarn.text = "警告:前方发现敌人";
}
b.クロス積