游戏主要是以场景为单位,实现的游戏不同场景地图切换,游戏角色的活动范围都是在游戏场景中,所以游戏场景的制作是整个游戏的基础。场景中主要包含的是地形、天空和模型,将它们制作好导入Unity场景中,调整好相互之间的比例、位置,就可以了。接下来讲解场景的制作: 本文制作的场景1地形是海边村落和岛屿,村落和岛屿隔海遥遥相望,场景2的地形是山中的一条河谷。整个地形制作使用的是world machine地形绘制工具,以场景1为例,首先通过使用布局工具(Layout Generator)用线或者多边形等方式描绘基本地形高低起伏,分别画出村落丘陵和岛屿,借用高级纹理(Advanced Perlin)进行精细表现调节,在程序左边的控制栏中设定水面高度,显示水面效果(show Water Lever),再使用联合工具(Combiner)将同一位置的不同表现相异(Differences),再进行简单地形(Simple Transform)处理和流水侵蚀(Erosion)效果处理,最后用颜色编辑器(colorizer)为不同高度海拔的地形设定不同的颜色,添加色彩效果,再显示出来,如图4.1所示。 1.1.3.1 建筑模型
基础场景制作完成后便可以开始建筑等的制作了,游戏中设定了一个靠海的村落,而作为一个村落应该要有房屋、器械等物体,这样才能够符合村落的设定,所以接下来的场景制作需要用3Ds Max来进行房屋等模型的制作。3Ds Max中可以构建各种几何体、平面、线、胶囊体等。 利用预设结构建造的过程中可以使用程序预设的修改器来进行辅助设计,3Ds Max提供了各式各样的修改器来帮助设计者在设计时能更加高效、轻松、简洁的制作出更加细腻的模型。 设计者利用多种多样的对象模型和修改器建立出自己想要的模型后还需要通过给对象赋予材质和贴图让模型拥有设计者心目中的质感。本文设计过程中主要使用的是长方体、圆锥体、门、窗、墙、楼梯等对象以及可编辑的多边形修改器、对称修改器等。 一般来说,建筑物都是非常规整的立体结构,大体上结构上都是左右对称的,所以当我们在制作一个建筑模型的时候可以先制作出模型的一半,然后将另一半删除后添加对称修改器,这样不仅快速省事还能使建筑左右两边完美一致。在添加对称修改器时要注意的是模型的位置最好在中心点位置上,这样比较容易使用轴对称。在制作的过程中要灵活在点、线、面各个层级之间切换,通过连接、挤压、桥接、倒角、切角、塌陷、对齐等常用工具的帮助可以快速的制作出设计者自己想要实现的对象结构。在制作完成建筑的基本细节后,若是建筑的某一边需要进行不一致的处理可以塌陷修改器然后单独处理某一边需要修改的那一部分而不会影响另一边。相似的建筑可以按住shift向某方向移动即可复制出一个一样的建筑,节省制作时间,对复制出来的建筑做细节修改相互之间不会影响。建筑还可以一个部分、一个部分的分开制作,制作完成后选中对象在父级别选择附加,点选要附加的对象就能使它们成为同一个对象。 角色分为人物和动物,人物模型很是复杂,要分为头部、身体来分别制作,头部可以采用左右对称修改器制作,用线描绘出头部轮廓,从眼眶开始,将五官分别制作再连接起来,最后将脸部完成,小技巧就是若是不能很好的把握面部比例关系可以将草图放在后面照着勾勒。之后再制作好身体部分的模型,将两部分合成一个整体,贴上贴图就完成了。动物模型也可以采用对称的方式来制作,在建立模型之前首先要了解动物的基本结构:头、上身、下身、四肢,在了解了之后再开始建立模型。由于的头、身体基本上可以看成球体,所以建模的时候一般选择分段数较少且为偶数的球体,之后使用对称修改器。将各个部分制作好后连接起来,调整好相对位置确定好比例关系,贴上贴图就完成了。 若是想要进行毛发的设置则可以使用3Ds Max内置的Hair和fur修改器进行处理,它可以根据设计者自己不同的想法生成毛发不同的颜色、长短、粗细、卷曲度等,也可以利用法线贴图将毛发拟真实化。 摄像头本身是没有脚本的,在游戏中,为了给玩家带来便利,能够多角度的灵活观察周围场景,可以给摄像头编写一个脚本,让摄像头能够跟随鼠标按键而旋转。 由于是第三人称游戏,所以摄像头要绑定在玩家角色身上,在一开始要设置摄像头与角色之间的距离,预先就设置好参数,获取角色的三维空间坐标将镜头对准角色。游戏视野的旋转是通过获取鼠标右键的点击事件来变换摄像头的角度,若角度超过了360度则进行角度换算;游戏视野的缩放是通过获取鼠标的滚轮滚动事件来变换摄像头与角色之间的距离,为了不让距离超过太多,要设置好最大距离,若超过最大距离则将最大距离值赋予给参数。 具体实现代码如下: using UnityEngine; using System.Collections; public class PlayerFlowOrbitCamera : MonoBehaviour { // Target to look at public Transform TargetLookAt; // Camera distance variables public float Distance = 20.0f; public float DistanceMin = 5.0f; public float DistanceMax = 15.0f; float startingDistance = 0.0f; float desiredDistance = 0.0f; // Mouse variables float mouseX = 0.0f; float mouseY = 0.0f; public float X_MouseSensitivity = 5.0f; public float Y_MouseSensitivity = 5.0f; public float MouseWheelSensitivity = 5.0f; // Axis limit variables public float Y_MinLimit = -35.0f; public float Y_MaxLimit = 60.0f; public float DistanceSmooth = 0.025f; float velocityDistance = 0.0f; Vector3 desiredPosition = Vector3.zero; public float X_Smooth = 0.05f; public float Y_Smooth = 0.1f; // Velocity variables float velX = 0.0f; float velY = 0.0f; float velZ = 0.0f; Vector3 position = Vector3.zero; void Start() { Distance = Vector3.Distance(TargetLookAt.transform.position, gameObject.transform.position); if (Distance > DistanceMax) DistanceMax = Distance; startingDistance = Distance; Reset(); } // Update is called once per frame void Update() { } // LateUpdate is called after all Update functions have been called. void LateUpdate() { if (TargetLookAt == null) return; HandlePlayerInput(); CalculateDesiredPosition(); UpdatePosition(); } void HandlePlayerInput() { // mousewheel deadZone float deadZone = 0.01f; if (Input.GetMouseButton(1)) { mouseX += Input.GetAxis("Mouse X") * X_MouseSensitivity; mouseY -= Input.GetAxis("Mouse Y") * Y_MouseSensitivity; } // this is where the mouseY is limited - Helper script mouseY = ClampAngle(mouseY, Y_MinLimit, Y_MaxLimit); // get Mouse Wheel Input if (Input.GetAxis("Mouse ScrollWheel") < -deadZone || Input.GetAxis("Mouse ScrollWheel") > deadZone) { desiredDistance = Mathf.Clamp(Distance - (Input.GetAxis("Mouse ScrollWheel") * MouseWheelSensitivity), DistanceMin, DistanceMax); } } void CalculateDesiredPosition() { // Evaluate distance Distance = Mathf.SmoothDamp(Distance, desiredDistance, ref velocityDistance, DistanceSmooth); // Calculate desired position -> Note : mouse inputs reversed to align to WorldSpace Axis desiredPosition = CalculatePosition(mouseY, mouseX, Distance); } Vector3 CalculatePosition(float rotationX, float rotationY, float distance) { Vector3 direction = new Vector3(0, 0, -distance); Quaternion rotation = Quaternion.Euler(rotationX, rotationY, 0); return TargetLookAt.position + (rotation * direction); } // update camera position void UpdatePosition() { float posX = Mathf.SmoothDamp(position.x, desiredPosition.x, ref velX, X_Smooth); float posY = Mathf.SmoothDamp(position.y, desiredPosition.y, ref velY, Y_Smooth); float posZ = Mathf.SmoothDamp(position.z, desiredPosition.z, ref velZ, X_Smooth); position = new Vector3(posX, posY, posZ); transform.position = position; transform.LookAt(TargetLookAt); } // Reset Mouse variables void Reset() { mouseX = 0; mouseY = 0; Distance = startingDistance; desiredDistance = Distance; } // Clamps angle between a minimum float and maximum float value float ClampAngle(float angle, float min, float max) { while (angle < -360.0f || angle > 360.0f) { if (angle < -360.0f) angle += 360.0f; if (angle > 360.0f) angle -= 360.0f; } return Mathf.Clamp(angle, min, max); } }1 游戏总体实现
1.1 场景制作
1.1.1 地形、地貌制作
在World Machine中完成了地形主体制作后,模型导出为.raw格式贴图导出为.png格式的位图,打开Unity 3D,在场景中新建一个地形(Terrain),导入Height Map选择之前导出的.raw文件,再为地形贴上之前同时导出的位图。由于导入后有一些方位差异,所以要注意把位图先水平翻转并旋转180°再导入进来,调整好大小即可。如图4.2所示:
但是如果没有灯光效果的话场景会显得很昏暗,所以可以创建两个平行光,一个从左边照射但是光线稍暗一点,另一个从右边照射光线正常就能产生太阳光照射的感觉了,如图4.3所示。
1.1.3 模型制作
1.1.3.2 角色制作
1.1.3.3 摄像头设置
- 上一篇: 学生作品19---游戏总...
- 下一篇: 学生作品21