射击游戏模板研究笔记

概述

这篇笔记记录研究其他射击游戏项目对一些问题的解决方案。主要有:

1.TPP如何改变人物仰角;

2.枪的挂载位置旋转,是每把枪各异还是用统一数据;

3.相机和人物的旋转,谁带动谁;

4.FPP和TPP的动作要求不同,是否用了两套动作;

5.使用的动画是否为humanoid;

FPS Animation Framework

Welcome! | FPS Animation Framework Legacy (gitbook.io)

动作条件判断测试

先对它做射击游戏笔记里的那一套动作条件判断测试。

1.跑步时按换弹被忽略;

2.换弹时按跑步被忽略;

3.瞄准状态按换弹,并没有解除瞄准,而是相机在瞄准位置换弹,但很明显相机不是枪的子物体,而是一直看前方;瞄准状态按跑步,退出瞄准开始跑步;

13d29c7ce4bc494c841d94841e3b6aed.png27e70342a93547bf8b20137db1269601.png

4.换弹中按瞄准,和3一样会进入瞄准换弹状态;跑步中按瞄准,被忽略;

7.趴下中按换弹,双手播放了换弹动画,M4的换弹动画没问题,另外几把枪趴下的换弹动画枪会直接消失,换完弹再回来;趴下中按跑步,趴下后开始往前爬;趴下中按瞄准,瞄准好像可以和任何动作叠加,就是把相机往前一点;

f966cdba11bb4a32b24b1788aa0a1d92.png

8.爬行中按瞄准,相机往前移了,双手是介于爬行和瞄准之间的动作;我感觉这个系统应该是用了混合树之类的技术;

35f7151172b4482f830c225a3bcfa22f.png

另外发现

demo里一共5把枪,换到最后一把有可能会不指向中心,指向偏左的位置,换成下一把M4,也是偏左的,再换下一把AK就正常了。

09cabfc7a3474625932d9dbd04213de9.png282b32995ee14e7f9b43ace12fea39c0.png

趴下时不能换枪。

趴下时后面几把枪的换弹动画好像没做好。

这个框架自制的组件。看起来挺复杂。

cce01db5a91a4950ac64885a6b00ea8d.png

瞄准相机位

侧向移动的时候枪相对于瞄准相机有偏移,说明瞄准相机不是简单的作为枪的子物体。

e4abf112ba6a4132955fcdf9ec920bae.png

Third Person Shooter Bundle

1771dfb0ca4741059115e4b99ab80e3f.png

1.改变人物仰角

在ShootBehaviour脚本。使用的是animator.SetBoneLocalRotation()。第一个对Spine设置是改变水平旋转,第二个对Chest设置是改变仰角。根据相机forward得到仰角,加一个修正值armsRotation,绕transform.right旋转,就是绕人物x轴旋转,先不看对Long  weapons的特殊处理,后面的代码要怎么理解?

public void OnAnimatorIK(int layerIndex)
	{
		if (isAiming && activeWeapon > 0)
		{
			if (CheckForBlockedAim())
				return;

			// Orientate upper body where camera  is targeting.
			Quaternion targetRot = Quaternion.Euler(0, transform.eulerAngles.y, 0);
			targetRot *= Quaternion.Euler(initialRootRotation);
			targetRot *= Quaternion.Euler(initialHipsRotation);
			targetRot *= Quaternion.Euler(initialSpineRotation);
			// Set upper body horizontal orientation.
			behaviourManager.GetAnim.SetBoneLocalRotation(HumanBodyBones.Spine, Quaternion.Inverse(hips.rotation) * targetRot);

			// Keep upper body orientation regardless strafe direction.
			float xCamRot = Quaternion.LookRotation(behaviourManager.playerCamera.forward).eulerAngles.x;
			targetRot = Quaternion.AngleAxis(xCamRot + armsRotation, this.transform.right);
			if (weapons[activeWeapon] && weapons[activeWeapon].type == InteractiveWeapon.WeaponType.LONG)
			{
				// Correction for long weapons.
				targetRot *= Quaternion.AngleAxis(9f, this.transform.right);
				targetRot *= Quaternion.AngleAxis(20f, this.transform.up);
			}
			targetRot *= spine.rotation;
			targetRot *= Quaternion.Euler(initialChestRotation);
			// Set upper body vertical orientation.
			behaviourManager.GetAnim.SetBoneLocalRotation(HumanBodyBones.Chest, Quaternion.Inverse(spine.rotation) * targetRot);
		}
	}

对四元数做实验可知:一个物体的世界旋转是从它的根父级到它的局部旋转相乘的的积:这里相乘顺序不能错,必须从根父级到它本身,因为四元数乘法不满足交换律!

[ContextMenu("看看四元数")]
    void PrintQuaternion(){
        Debug.Log("这个物体的世界旋转是"+transform.rotation);
        Debug.Log("这个物体和它父级的局部旋转的积是"+transform.parent.localRotation*transform.localRotation);
    }

73749fbfdda9441da2eab2808ab16de2.png

所以这个targetRot应该是chest在改变仰角之后的世界旋转

SetBoneLocalRotation(HumanBodyBones.Chest, Quaternion.Inverse(spine.rotation) * targetRot);

那么SetBoneLocalRotation里的Quaternion.Inverse()作用好像是和targetRot里的世界旋转成分抵消,使结果是chest需要设置的局部旋转。总之应该可以用一句spine.InverseTransformDirection(transform.right)代替。

SetBoneLocalRotation(HumanBodyBones.Chest, Quaternion.Inverse(spine.rotation) * targetRot);

又看了一下Quaternion.Inverse()的作用:

[ContextMenu("旋转和Inverse相乘")]
    void PrintInverse(){
        Debug.Log(Quaternion.Inverse(transform.rotation)*transform.rotation);
    }

果然Inverse和自己相乘是单位四元数:

7723d6967081489db738411d2ac7b4d4.png

学会了一种寻找人体部位的新方法animator.GetBoneTrasform(HumanBodyBones.XXX);比transform.Find("XXX/XXX/XXX")方便,不受人物骨架结构变化的影响。

432753c3ee7444039191bdcfcd701d3d.png

2.武器挂载

挂载在右手,枪的局部旋转是90度的整数倍,位置不是(0,0,0),枪的脚本里记录了枪的局部位置和旋转。

a06c2ab192ae480da7b7dba0f8ebf78b.png

3.人物和相机的旋转

研究1的时候已经知道,是把相机的仰角传给人物由于改变仰角,所以是玩家控制相机,相机带动人物。

Low Poly FPS Pack

2.武器挂载

这是一个人物只有手臂的纯FPS模板。从这个项目可以看出纯FPS游戏:

1.手臂和枪被打成一个fbx文件,属于一个模型(所以无需在游戏引擎里调整和记录枪的局部位置旋转),换枪的时候是手臂和枪的模型整体替换,扔枪的时候则是实例化了一把枪扔出去,把手臂模型替换成不拿枪的;

2.手臂和枪都由骨骼控制,且控制手臂、枪、弹匣的骨骼都是平级的,不存在靠父子关系带动;

3.由于手臂和枪是一个整体,手臂和枪互动的动画比如换弹、拉栓可以做得很细致,而如果是TPS,人物和枪是分离的物体,这就涉及到一个animator带动另一个animator转换状态的问题。

d3d12b3d561b448f89d23a5cc23dd48b.png3b2c8b1ea3eb40c7ab3e2b315507d322.png

3.相机和人物的旋转

这里是把相机、人物手臂、UI共同作为一个空节点的子节点,对这个空节点做旋转。

4974f6371cf942e6b0009e3ff881544d.png

瞄准镜实现

这个方案的瞄准镜是局部放大。是用双相机实现的。

f9b756532a1f4450b14cdc949e81a488.png

一个相机渲染手臂和枪。

3b7e4bc323044170b392287a67e2ac13.png

Clear Flags=Depth only:Clear Flags意思是画面里没有物体的部分画什么,Depth only我理解是画Depth小于这个相机的相机画的内容。但是我选Dont Clear也是一样的效果。

Culling Mask=Nothing:意思是什么都不渲染,但是为什么渲染了手臂和枪?我又选了一下Nothing,然后就都不渲染了。

ab88086015bd42a7b19a233c29dabcd2.png

手臂和枪的Layer是空,我只有选Everything或勾选所有层才能渲染手臂和枪。如果一个物体Layer是空,我在Culling Mask下拉框里就看不到它。

cae7abd13f71432db2cf2683c728cb60.png

给一个物体指定Layer时不允许指定空,但是初始却可以是空。

ab9b9636fa1b48119660e3ac80b8467a.png

写了个脚本打印这个物体的Layer:

[ContextMenu("看看Layer")]
    void PrintLayerThis(){
        Debug.Log(gameObject.layer);
    }

显示是8.

72d61e17e9354263a9192e346bc974cb.png

Layer列表里第8层没名字。

ea4d23b555e846e9bf6a5d0208a3f4b9.png

又写了个设置Layer的方法:

[ContextMenu("设置Layer")]
    void SetLayer(){
        gameObject.layer=10;
    }

可以设置成那个序号层,即使它是空的。

6c5f8252bac04bc0adbd537e4a90e045.png

综上,可以用脚本gameObject.Layer=设置成空Layer,但是编辑器界面不能设置成空Layer。脑残的设计。

所以上面的Culling Mask=Nothing也不是真Nothing,而是渲染了一些空Layer。我把第8层改名叫Player,Culling Mask就变Player了。

d8a1dcd306234e838203b5ca105c6f52.png

Depth=1:先渲染Depth=0,再渲染这个。

afcaea732fbd49dbaa76fc99b026ff02.png

前面设置玩家相机不渲染环境,但是瞄准镜里还是要看到远处的环境,这里用了第三个相机,输出到Texture,这个Texture放在瞄准镜后端,后面还有一个镜片物体,开镜的时候镜片使用透明贴图,没开镜时使用全黑贴图。

744ba4b9db5b41edac4c37586651e10e.png08c0e72380df4060a009a09eef59afa7.png

Unity - Manual: Camera component

44b4d0bb112c4fa8b7156f35bd83dc07.png

渲染世界的相机

b720b79d219441e1a3e5deef28d5bc2b.pngf8bb92eaadf44c8f9c1e4001b194a10e.png

JU TPS

1.

使用了一些节点作为拿各种武器的IKGoal,好像根本没有持各种武器的动画,完全是用IK摆出来的。

05996770e5554d90a7db3e3ee53b27a9.png

2.武器挂载

枪挂在手上。

346f468ac86648669ebab4ee35e26258.png

枪的位置旋转是不规则的数据,且每把枪不一样……那这些数据要怎么记录?

29c39ae3f92f4dc484b517183c5c5ea4.png7f4405f916ec44d4bb95169be36eb2c7.pnga0490b352af3455592a46c5290db1438.png

答案是:所有枪都在手上挂一份,身上挂一份,使用的时候把手上的枪激活,身上的枪隐藏。只存在枪的激活和隐藏,不存在转移……

74f81d6c0dda45dc8f3513c47c38844b.png

3.相机和人物的关系

二者没有直接的父子关系。

7718a84269f4484ebeab2d2b7f56ff25.png

通过自制的脚本跟随人物。也就是人物带动相机。

dd5b3751636f4c9e8667dc0eda20f01b.png

求生之路

调出了第三人称,发现这么几点:

1.第三人称的弹着点不在准星处,偏右下;

2.走路的时候枪并没有稳定指向前方,而发射子弹是朝前方,子弹的发射位置和向量并不是枪口、枪的正前方;

3.通过旋转手臂改变仰角,第三人称动作能达到的仰角范围小于实际的仰角范围;

4.步枪的换弹动作是同一个;

3b1277ce644140fa9997b8531b8dd940.jpegf780e77e5f854f6896f81ee8dc3b32db.jpeg8fe0ddcc53374aff82a3ab123dd2aed3.jpeg

PUBG人物动作素材

在tb上买了一套吃鸡的动作素材。

把一个人物模型拖进来,可以看到:

1.身体和头分成两个网格,为了在第一人称隐藏头,防止挡第一人称相机;

2.有很多ik节点,用来动态调整人物的动作;

把骨架进一步展开:能看到近战武器、投掷物、背包、第一人称相机、主武器、副武器挂载点;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值