unity3d实战_unity3d游戏制作

unity3d实战_unity3d游戏制作[Unity3D入门]分享一个自制的入门级游戏项目"坦克狙击手"我在学Unity3D,TankSniper(坦克狙击手)这个项目是用来练手的。游戏玩法来自这里(http://www.4399.com/flash/127672_3.htm),虽然抄袭了人家的创意,不过我只用来练习(目前还很不成熟,离人家的境界相差很大),坦克、导弹、建筑模型来自网络,应该不会有版权问题吧。由于模型和代码总共…

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

[Unity3D入门]分享一个自制的入门级游戏项目”坦克狙击手”

我在学Unity3D,TankSniper(坦克狙击手)这个项目是用来练手的。游戏玩法来自这里(http://www.4399.com/flash/127672_3.htm),虽然抄袭了人家的创意,不过我只用来练习(目前还很不成熟,离人家的境界相差很大),坦克、导弹、建筑模型来自网络,应该不会有版权问题吧。

由于模型和代码总共10M以上了,需要源代码和发布的Windows版、网页版程序的同学麻烦支付100元并留下你的邮箱~

unity3d实战_unity3d游戏制作

 

到目前为止,用到的Unity3D知识有:地形Terrain,子物体gameObject,预制体Prefab,粒子系统Shuriken,刚体rigidbody,碰撞体collider,场景scene。

本文将非常简略,因为我也不知道该详写什么略写什么。有任何问题的话请留言,我会详细回复,并且根据情况加入正文。

需要step by step指导的同学,可以参考(http://pixelnest.io/tutorials/2d-game-unity/)。我就是从这篇文章开始学习Unity3D的。有了这个基础,看本文就没有什么问题了。

如何创建大量坦克

目前TankSniper里有4个坦克模型。如你所见,游戏中需要出现大量的坦克。在Unity3D中,我们不用new SomeTank()这种方式创建坦克,而是用Unity3D自带的Instantiate(prefab)方法创建坦克。其中的prefab就是预先设计订制的坦克模板,所以叫预制体。

创建预制体很简单,你只需

  • 在Hierarchy中创建一个Cube。
  • 把导入的坦克模型拖拽到Hierarchy面板。
  • 调整Cube和坦克模型的position、rotation、Scale,使Cube恰好包住坦克模型,然后把坦克模型拖拽到Cube下,成为Cube的子物体
  • 把Cube拖拽到Project面板的Asset文件夹下(或Asset的子文件夹下)。

这样,一个以Cube为名称的预制体就做好了。以后你就可以在C#脚本中通过写

Instantiate(Cube);

这样的句子来创建坦克了。

一个小问题是,为什么要把坦克模型当做Cube的子物体?理由有2:首先,这样可以任意调整坦克模型的transform属性,而预制体整体的transform仍旧可以是0,0,0,这样方便使用;然后,用Cube严密包裹坦克模型后,Cube可以作为碰撞检测的边界,长方体之间的碰撞计算量比复杂的坦克模型要小得多。这是一种常用的做法。

 

爆炸效果和导弹尾焰

爆炸和尾焰都是用粒子系统做的,通过调整粒子系统的参数就可以实现,而且我没有用任何纹理图片。视觉效果虽然一般,不过目前这不是我要学的重点,暂时知足常乐一下好了。

unity3d实战_unity3d游戏制作

unity3d实战_unity3d游戏制作

 

导弹攻击坦克

实际上就是在碰撞事件OnCollisionEnter中写代码:在导弹的OnCollisionEnter事件中添加爆炸的粒子系统并销毁导弹;在坦克的OnCollisionEnter事件中减掉一定数值的HP值,若HP<=0了,就用Unity3D自带的Destroy()方法销毁坦克。

unity3d实战_unity3d游戏制作
unity3d实战_unity3d游戏制作

 1     void OnCollisionEnter(Collision collision) { //当碰撞体与刚体与其他碰撞体或刚体接触时调用
 2 //        foreach (ContactPoint contact in collision.contacts) {
 3 //            Debug.Log(string.Format("{0}", contact.ToString()));
 4 //            Debug.DrawRay(contact.point, contact.normal, Color.white);
 5 //        }
 6 //        if (collision.relativeVelocity.magnitude > 2)
 7 //            audio.Play();
 8         foreach (ContactPoint contact in collision.contacts) {
 9             ExplosionEffectHelper.Instance.Explode(ExplosionEffectHelper.ExplosionEffect.MissileExplosion, contact.point);
10             SoundEffectHelper.Instance.MakeExplosionSound();
11             Destroy(this.gameObject);
12             break;
13         }
14     }

MissileScript.cs

unity3d实战_unity3d游戏制作
unity3d实战_unity3d游戏制作

 1     void OnCollisionEnter(Collision collision) { //当碰撞体与刚体与其他碰撞体或刚体接触时调用
 2         //foreach (ContactPoint contact in collision.contacts) {
 3         //    Debug.DrawRay(contact.point, contact.normal, Color.white);
 4         //}
 5         //if (collision.relativeVelocity.magnitude > 2)
 6         //    audio.Play();
 7         var missileScript = collision.gameObject.GetComponent<MissileScript>();
 8         if (missileScript != null) {
 9             var power = missileScript.power;
10             this.Damage(power);
11         }
12     }

TankHealth.cs

最开始我用的是OnTriggerEnter事件。不过OnTriggerEnter无法获取导弹和坦克碰撞的准确位置,也就无法在最准确的位置释放爆炸效果,所以换成了OnCollisionEnter。

关于isTrigger与触发OnTriggerEnter、OnCollisionEnter之间的关系,可参考(http://www.cnblogs.com/infly123/p/3920393.html),本文不再详细说明。

 

发射导弹

导弹也要做成预制体

我的设定是:鼠标左键按下时,在摄像机正下方距地面一定高度处发射导弹,导弹速度方向要指向点击到的三维场景中的坐标。这就要求从屏幕坐标转换到世界坐标。我愁了两天,终于找到了办法。

unity3d实战_unity3d游戏制作
unity3d实战_unity3d游戏制作

 1     // 每帧调用一次,用于更新游戏场景和状态(和物理状态有关的更新应放在FixedUpdate里)
 2     void Update () {
 3         if (Input.GetMouseButtonDown(0)) { shooting = true; }
 4         if (Input.GetMouseButtonUp(0)) { shooting = false; }
 5         
 6         if (shooting) {
 7             elapsedInterval += Time.deltaTime;
 8             if (elapsedInterval >= shootInterval) {
 9                 elapsedInterval = 0;
10                 Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);//从摄像机发出到点击坐标的射线
11                 RaycastHit hitInfo;
12                 if (Physics.Raycast(ray, out hitInfo)) {
13                     /*
14                     Debug.DrawLine(ray.origin, hitInfo.point);//划出射线,只有在scene视图中才能看到
15                     GameObject gameObj = hitInfo.collider.gameObject;
16                     Debug.Log(string.Format("Clicked object's name: {0}", gameObj.name));
17                     */
18                     Transform missile = Instantiate(missilePrefab) as Transform;
19                     Vector3 position = Camera.main.transform.position;
20                     missile.position = new Vector3(position.x, position.y * 2 / 3, position.z);
21                     Vector3 dirPos = (hitInfo.point - missile.position);
22                     dirPos.Normalize();
23                     missile.gameObject.rigidbody.velocity = dirPos * 150;
24                     SoundEffectHelper.Instance.MakePlayerShotSound();
25                 }
26             }
27         }
28     }

ShootMissile.cs

这时你会发现,导弹虽然按照要求的方向走了,但是全部是像螃蟹一样横着飞过去的。这不科学。所以要把导弹的旋转方向调整到飞行方向。这个问题我又琢磨了一天,找到了办法。

unity3d实战_unity3d游戏制作
unity3d实战_unity3d游戏制作

 1     static readonly Vector3 missileInitialRotation = new Vector3(-1, 0, 0);
 2     // 每帧调用一次,用于更新游戏场景和状态(和物理状态有关的更新应放在FixedUpdate里)
 3     void Update () {
 4         if (Input.GetMouseButtonDown(0)) { shooting = true; }
 5         if (Input.GetMouseButtonUp(0)) { shooting = false; }
 6         
 7         if (shooting) {
 8             elapsedInterval += Time.deltaTime;
 9             if (elapsedInterval >= shootInterval) {
10                 elapsedInterval = 0;
11                 Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);//从摄像机发出到点击坐标的射线
12                 RaycastHit hitInfo;
13                 if (Physics.Raycast(ray, out hitInfo)) {
14                     /*
15                     Debug.DrawLine(ray.origin, hitInfo.point);//划出射线,只有在scene视图中才能看到
16                     GameObject gameObj = hitInfo.collider.gameObject;
17                     Debug.Log(string.Format("Clicked object's name: {0}", gameObj.name));
18                     */
19                     Transform missile = Instantiate(missilePrefab) as Transform;
20                     Vector3 position = Camera.main.transform.position;
21                     missile.position = new Vector3(position.x, position.y * 2 / 3, position.z);
22                     Vector3 dirPos = (hitInfo.point - missile.position);
23                     dirPos.Normalize();
24                     missile.rotation = Quaternion.FromToRotation( //从螃蟹式到科学式,需要这样的旋转。
25                         missileInitialRotation, //螃蟹式的旋转向量
26                         dirPos); //科学式的旋转向量
27                     missile.gameObject.rigidbody.velocity = dirPos * 150;
28                     SoundEffectHelper.Instance.MakePlayerShotSound();
29                 }
30             }
31         }
32     }

ShootMissile.cs

 

目前的缺点

如你所见,有的坦克由于前后撞击加上地形起伏,竟然飞了起来。我已经用代码和物理属性调整过,但还是没有完全消除这种情况。

导弹尾焰和爆炸效果还不是很理想。

没有开始、存档、选项等菜单,没有我方HP、关卡、敌方剩余坦克数等信息。

敌方坦克还不会开炮。(欺负人。。。)

敌方坦克只知道向右(Z轴正方向)走,没有一点AI。

导弹只能攻击命中的坦克,对附近的坦克没有波及伤害。

总结

有了Unity3D,做游戏涉及的很多算法都不需要自己写了。Unity3D对提高生产效率的确有非常大的帮助。

需要源代码和发布的Windows版、网页版程序的同学麻烦支付100元并留下你的邮箱~

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/169337.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • EM算法(Expectation Maximization Algorithm)详解

    EM算法(Expectation Maximization Algorithm)详解EM算法(ExpectationMaximizationAlgorithm)详解主要内容EM算法简介预备知识极大似然估计Jensen不等式EM算法详解问题描述EM算法推导EM算法流程EM算法优缺点以及应用1、EM算法简介  EM算法是一种迭代优化策略,由于它的计算方法中每一次迭代都分两步,其中一个为期望步(E步),另一个为极大步(M步),所以算法被称…

  • centos7.6开放端口命令_查看端口有没有开放

    centos7.6开放端口命令_查看端口有没有开放概要最近在docker下搭建MySQL和Redis环境,远程linux主机内部网络都走通了,但是就是外网无法连接远程服务器的MySQL和Redis。经过一番查找和学习,终于找到了问题,不仅远程服务器上docker要做好内部和外部端口的映射,关键还要对对外开放的端口添加到防火墙中。内容介绍的逻辑是:本篇文章先记录Centos7下查看防火墙状态和网络状态命令;下一篇将介绍通过docker…

  • 基于协同过滤的推荐系统设计_基于分类的协同过滤

    基于协同过滤的推荐系统设计_基于分类的协同过滤http://blog.csdn.net/pipisorry/article/details/51788955(个性化)推荐系统构建三大方法:基于内容的推荐content-based,协同过滤collaborativefiltering,隐语义模型(LFM,latentfactormodel)推荐。这篇博客主要讲协同过滤。协同过滤CollaborativeFiltering协同过滤:使用

    2022年10月26日
  • python fillna函数_python中dropna函数

    python fillna函数_python中dropna函数我正在尝试在datetime64[ns]类型的列上运行fillna.当我运行类似的东西:DF[‘日期’].fillna(日期时间(“2000-01-01”))我明白了:TypeError:需要一个整数有什么方法吗?这应该在0.12和0.13(刚刚发布)中工作.@DSM指出日期时间的构造如下:datetime.datetime(2012,1,1)所以错误是由于未能构建您传递给fillna的值…

  • 经典分页样式

    经典分页样式$pagenum=@ceil($count/$perpage1);if($page!=0){$page_jian=$page-1;$page_home.="<ahref=&#39

  • 手机靓号正则表达式「建议收藏」

    手机靓号正则表达式「建议收藏」手机靓号正则表达式手机靓号正则ABC+=1234或12345…AAAA+=1111或11111…AAAA+//ABC+DDD+//AA+BBB+//AABBCC//ABABABAAAA+    (\d)\1{3,}   //如果想调3A+改{3,}改成{2,},想固定3A的话把{2,}的{,}号去掉  (1111+)ABC+DDD+  (?:0(?=1)|1(?=2)|2(?=3)|3(?=4

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号