2/3D游戏:3D
辅助插件:角色控制器
游戏制作难度系数:中级
用到的其他工具:network
一、解决由于子弹射击速度过快而无法打到物体的问题
//方法一: public float Speed = 800; Vector3 originalPos; void Update() { originalPos = transform.position; //获取子弹现在的位置 transform.Translate(Vector3.forward * Speed * Time.deltaTime); //移动子弹,每秒移动800米 Vector3 direction = transform.position - originalPos; //获取子弹移动的方向 float distance = (transform.position - originalPos).magnitude; //获取子弹移动的距离 RaycastHit hit; if (Physics.Raycast(originalPos, direction, out hit, distance)) { //其他逻辑操作。。。 } } //方法二: public float Speed = 100000; Vector3 startPos; Vector3 endPos; void Start() { //给子弹施加一个向前的力 GetComponent<Rigidbody>().AddForce(Vector3.forward * Speed, ForceMode.Force); } void Update() { startPos=endPos; endPos=transform.position; float distance = (startPos - endPos).magnitude; //获取子弹移动的距离 Ray r = Camera.main.ScreenPointToRay(startPos); RaycastHit hit; if (Physics.Raycast(r, out hit, distance)) { //其他逻辑操作。。。 } }
二、解决弹痕的位置问题
因为弹痕是一个贴图,所以当射击到某个点上时,我们要把此贴图贴在此点上面,具体实现代码如下:
GameObject goo = Instantiate(go, hit.point, Quaternion.identity) as GameObject;//实例化一张弹痕贴图 goo.transform.LookAt(hit.point - hit.normal); //使弹痕贴图面向法线上的点 LookAt:旋转物体使z轴指向目标物体。 goo.transform.Translate(Vector3.back * 0.01f); //使弹痕贴图向上移一点,避免贴图与地面重合而造成弹痕贴图显示不正常或无法显示
三、设置弹痕缓慢消失的效果
public float speed = 0.3f; private float lefttime = 0; Material meterial; void Start() { meterial = renderer.material; } void Update() { if (meterial.color.a < 0.005) { Destroy(this.gameObject); } lefttime += Time.deltaTime; if (lefttime > 2f) //弹痕出现2秒后,开始执行逐渐透明效果 { meterial.color = Color.Lerp(meterial.color, Color.clear, speed * Time.deltaTime); // Color.clear 为透明色,设置物体逐渐透明 } }
四、设置头盔在骨骼关节下
因为动画是控制模型的骨骼关节,所以必须把头盔放在相应的骨骼关节下,才能实现头盔跟随动画的运动而运动,而不能放在模型的渲染(Mesh Renderer)节点下,渲染节点只是挂了一个渲染组件,来渲染模型的样子的!
五、解决动画和代码控制模型关节冲突的问题
一旦一个模型正在播放动画,我们是无法使用代码控制模型的关节的,因为模型的关节是被动画控制的,动画会在每一帧的update方法里面去控制关节的Transform(这里可以联想到http://www.cnblogs.com/MrZivChu/p/ik.html 基础 -> 3,从3下面的图中可以看出动画确实是控制模型的每一个关节的Transform的),所以我们必须在LateUpdate里面用代码控制模型的关节!
六、控制人物移动
使用CharacterController来控制,主要使用到了CharacterController自带实例的相关脚本
void Update() { if (characterController.isGrounded == false) { //播放下落的动画 networkView.RPC("PlayState", RPCMode.AllBuffered, "soldierFalling"); } else { float h = Input.GetAxis("Horizontal"); float v = Input.GetAxis("Vertical"); if (Mathf.Abs(h) > 0.05f || Mathf.Abs(v) > 0.05f) { networkView.RPC("PlayState", RPCMode.AllBuffered, "soldierWalk"); } else { networkView.RPC("PlayState", RPCMode.AllBuffered, "soldierIdle"); } } }