分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow

也欢迎大家转载本篇文章。分享知识,造福人民,实现我们中华民族伟大复兴!

这是一个横版射击游戏。教程来自:http://pixelnest.io/tutorials/2d-game-unity/中文版教程:http://www.litpo.com/category/易学的教程/
教程文章已经详细地介绍实现过程,这里就不再复述,只做一些简单的笔记记录,以供备忘。

1.创建第一个场景

新建工程。接着在"Project"面板上创建如下文件夹:

接着在"Hierarchy"面板上创建多个空对象,形成以下结构:

这些空对象的Position保持为(0, 0, 0)即可。保存场景,名称为"Stage1"。

2.添加显示背景

将背景图片放入"Textures"文件夹,确认这张图片的纹理类型,即"Texture Type"属性为"Sprite",如下图所示:

在场景中添加一个Sprite游戏对象,设置其"Sprite"属性为刚才导入的背景图片。重命名这个对象为"Background1",将其移动到"Level -> 0 - Background"里面,设置其"Position"为(0, 0, 0)。接着添加背景元素。导入平台图片到"Textures"文件夹,选中"platforms"图片,设置其"Sprite Mode"为"Multiple",然后点击"Sprite Editor",如下图所示:
在弹出的"Sprite Editor"窗口中,进行绘制每个平台的包围矩形,以便将纹理分割成更小的部分。然后分别命名为"platform1"和"platform2",如下图所示:

创建一个新的Sprite游戏对象,设置其"Sprite"属性为"platform1"。再在创建新Sprite对象,设置其"Sprite"属性为"platform2"。将它们放置到"1 - Middleground"对象里,并且确认它们的Z坐标为0。将这两个对象从"Hierarchy"面板拖动到"Project"面板下的"Prefabs"文件夹,保存成预制对象。接着,为了避免显示顺序问题,修改下游戏对象的Z坐标,如下所示:

Layer Z Position
0 - Background 10
1 - Middleground 5
2 - Foreground 0

此时,点击"Scene"面板上的2D到3D视图切换,可以清楚看到层次:

3.创建主角和敌人

导入主角图片到"Textures"文件夹,创建一个Sprite游戏对象,命名为"Player",设置其"Sprite"属性为刚才导入的主角图片。将此对象放入"2 - Foreground"层里,设置其Scale为(0.2, 0.2, 1)。接着,为主角添加盒碰撞体组件,点击"Add Component"按钮,选择"Box Collider 2D",设置其Size为(10, 10),虽然这还是大于实际的区域,但已比图片小多了,如下图所示:
(可以通过按住Shift键,来调整绿色碰撞范围)
接着,再为主角对象添加"Rigidbody 2D"刚体组件,现在运行可以看到如下结果:

可以看到主角往下落了,这是因为刚体带有重力,但在这个游戏不需要用到,将"Gravity Scale"属性设为0即可。另外,不想因为物理而引起的主角旋转,则将"Fixed Angles"属性勾选上。完整的设置如下图所示:


开始准备让主角移动。在"Scripts"文件夹里,创建一个C#脚本,名称为"PlayerScript",实现让方向键移动主角,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
using UnityEngine;

/// <summary>
/// Player controller and behavior
/// </summary>
public class PlayerScript : MonoBehaviour
{
  /// <summary>
  /// 1 - The speed of the ship
  /// </summary>
  public Vector2 speed = new Vector2(50, 50);

// 2 - Store the movement
  private Vector2 movement;

void Update()
  {
    // 3 - Retrieve axis information
    float inputX = Input.GetAxis("Horizontal");
    float inputY = Input.GetAxis("Vertical");

// 4 - Movement per direction
    movement = new Vector2(
      speed.x * inputX,
      speed.y * inputY);

}

void FixedUpdate()
  {
    // 5 - Move the game object
    rigidbody2D.velocity = movement;
  }
}

这里以改变刚体的速率来达到主角的移动,而不是通过直接改变"transform.Translate",因为那样的话,可能会不产生碰撞。将此脚本附加到主角对象上,现在运行,方向键来控制移动,如下图所示:

接下来,添加第一个敌人。导入章鱼敌人图片到"Textures"文件夹,创建一个Sprite游戏对象,命名为"Poulpi",设置其"Sprite"属性为刚才导入的图片,设置"Scale"属性为(0.4, 0.4, 1),添加"Box Collider 2D"组件,其Size为(4, 4),添加"Rigidbody 2D"组件,其"Gravity Scale"属性为0,并且勾选"Fixed Angles"属性框。将对象保存为预制。在这里只让章鱼简单地往前行,创建一个脚本,命名为"MoveScript",代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
using UnityEngine;

/// <summary>
/// Simply moves the current game object
/// </summary>
public class MoveScript : MonoBehaviour
{
  // 1 - Designer variables

/// <summary>
  /// Object speed
  /// </summary>
  public Vector2 speed = new Vector2(10, 10);

/// <summary>
  /// Moving direction
  /// </summary>
  public Vector2 direction = new Vector2(-1, 0);

private Vector2 movement;

void Update()
  {
    // 2 - Movement
    movement = new Vector2(
      speed.x * direction.x,
      speed.y * direction.y);
  }

void FixedUpdate()
  {
    // Apply movement to the rigidbody
    rigidbody2D.velocity = movement;
  }
}

将此脚本附加到章鱼对象上,现在运行,可以看到章鱼往前移动,如下图所示:

此时如果将主角放在章鱼前面,两个对象将会产生碰撞,互相阻塞对方的移动。

4.射击

导入子弹图片到"Textures"文件夹,创建一个Sprite游戏对象,命名为"PlayerShot",设置其"Sprite"属性为刚才导入的图片,设置"Scale"属性为(0.75, 0.75, 1),添加"Rigidbody 2D"组件,其"Gravity Scale"属性为0,并且勾选"Fixed Angles"属性框,添加"Box Collider 2D"组件,其Size为(1, 1),并且勾选"IsTrigger"属性。勾选"IsTrigger"属性表示该碰撞体用于触发事件,并将被物理引擎所忽略。意味着,子弹将穿过触碰到的对象,而不会阻碍对象的移动,触碰的时候将会引发"OnTriggerEnter2D"事件。创建一个脚本,命名为"ShotScript",代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
using UnityEngine;

/// <summary>
/// Projectile behavior
/// </summary>
public class ShotScript : MonoBehaviour
{
  // 1 - Designer variables

/// <summary>
  /// Damage inflicted
  /// </summary>
  public int damage = 1;

/// <summary>
  /// Projectile damage player or enemies?
  /// </summary>
  public bool isEnemyShot = false;

void Start()
  {
    // 2 - Limited time to live to avoid any leak
    Destroy(gameObject, 20); // 20sec
  }
}

将此脚本附加到子弹对象上,然后将"MoveScript"脚本也附加到子弹对象上以便可以移动。保存此对象为预制。接着,让碰撞产生伤害效果。创建一个脚本,命名为"HealthScript",代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
using UnityEngine;

/// <summary>
/// Handle hitpoints and damages
/// </summary>
public class HealthScript : MonoBehaviour
{
  /// <summary>
  /// Total hitpoints
  /// </summary>
  public int hp = 1;

/// <summary>
  /// Enemy or player?
  /// </summary>
  public bool isEnemy = true;

/// <summary>
  /// Inflicts damage and check if the object should be destroyed
  /// </summary>
  /// <param name="damageCount"></param>
  public void Damage(int damageCount)
  {
    hp -= damageCount;

if (hp <= 0)
    {
      // Dead!
      Destroy(gameObject);
    }
  }

void OnTriggerEnter2D(Collider2D otherCollider)
  {
    // Is this a shot?
    ShotScript shot = otherCollider.gameObject.GetComponent<ShotScript>();
    if (shot != null)
    {
      // Avoid friendly fire
      if (shot.isEnemyShot != isEnemy)
      {
        Damage(shot.damage);

// Destroy the shot
        Destroy(shot.gameObject); // Remember to always target the game object, otherwise you will just remove the script
      }
    }
  }
}

将此脚本附加到Poulpi预制体上。现在运行,让子弹和章鱼碰撞,可以看到如下结果:

如果章鱼的生命值大于子弹的伤害值,那么章鱼就不会被消灭,可以试着通过改变章鱼对象的"HealthScript"的hp值。接着,准备可以射击。创建一个脚本,命名为"WeaponScript",代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
using UnityEngine;

/// <summary>
/// Launch projectile
/// </summary>
public class WeaponScript : MonoBehaviour
{
  //--------------------------------
  // 1 - Designer variables
  //--------------------------------

/// <summary>
  /// Projectile prefab for shooting
  /// </summary>
  public Transform shotPrefab;

/// <summary>
  /// Cooldown in seconds between two shots
  /// </summary>
  public float shootingRate = 0.25f;

//--------------------------------
  // 2 - Cooldown
  //--------------------------------

private float shootCooldown;

void Start()
  {
    shootCooldown = 0f;
  }

void Update()
  {
    if (shootCooldown > 0)
    {
      shootCooldown -= Time.deltaTime;
    }
  }

//--------------------------------
  // 3 - Shooting from another script
  //--------------------------------

/// <summary>
  /// Create a new projectile if possible
  /// </summary>
  public void Attack(bool isEnemy)
  {
    if (CanAttack)
    {
      shootCooldown = shootingRate;

// Create a new shot
      var shotTransform = Instantiate(shotPrefab) as Transform;

// Assign position
      shotTransform.position = transform.position;

// The is enemy property
      ShotScript shot = shotTransform.gameObject.GetComponent<ShotScript>();
      if (shot != null)
      {
        shot.isEnemyShot = isEnemy;
      }

// Make the weapon shot always towards it
      MoveScript move = shotTransform.gameObject.GetComponent<MoveScript>();
      if (move != null)
      {
        move.direction = this.transform.right; // towards in 2D space is the right of the sprite
      }
    }
  }

/// <summary>
  /// Is the weapon ready to create a new projectile?
  /// </summary>
  public bool CanAttack
  {
    get
    {
      return shootCooldown <= 0f;
    }
  }
}

将这个脚本附加到主角对象上,设置其"Shot Prefab"属性为"PlayerShot"预制体。打开"PlayerScript"脚本,在Update()方法里面,加入以下片段:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
void Update()
  {
    // ...

// 5 - Shooting
    bool shoot = Input.GetButtonDown("Fire1");
    shoot |= Input.GetButtonDown("Fire2");
    // Careful: For Mac users, ctrl + arrow is a bad idea

if (shoot)
    {
      WeaponScript weapon = GetComponent<WeaponScript>();
      if (weapon != null)
      {
        // false because the player is not an enemy
        weapon.Attack(false);
      }
    }

// ...
  }

当收到射击的按钮状态,调用Attack(false)方法。现在运行,可以看到如下结果:

接下来,准备创建敌人的子弹。导入敌人子弹图片到"Textures"文件夹,选中"PlayerShot"预制体,按下Ctrl+D进行复制,命名为"EnemyShot1",然后改变其Sprite为刚才导入的图片,设置其Scale为(0.35, 0.35, 1)。接着,让章鱼可以射击。将"WeaponScript"脚本附加到章鱼对象上,拖动"EnemyShot1"预制体到其"Shot Prefab"属性,创建一个脚本,命名为"EnemyScript",用来简单地每一帧进行自动射击,代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
using UnityEngine;

/// <summary>
/// Enemy generic behavior
/// </summary>
public class EnemyScript : MonoBehaviour
{
  private WeaponScript weapon;

void Awake()
  {
    // Retrieve the weapon only once
    weapon = GetComponent<WeaponScript>();
  }

void Update()
  {
    // Auto-fire
    if (weapon != null && weapon.CanAttack)
    {
      weapon.Attack(true);
    }
  }
}

将此脚本附加到章鱼对象上,如下图所示:
现在运行,可以看到如下结果:

可以看到章鱼向右射击了子弹,这是因为代码就是让它那么做的。实际上,应该做到可以朝向任何方向射击子弹。在这里,创建一个空对象,命名为"WeaponObject",删除章鱼预制体身上的"WeaponScript"脚本,将"WeaponScript"脚本附加到"WeaponObject"对象上,并且拖动"EnemyShot1"预制体到其"Shot Prefab"属性,设置"WeaponObject"对象的"Rotation"属性为(0, 0, 180),然后保存为预制,如下所示:

接着,修改"EnemyScript",代码为如下:

Unity 4 3 制作一个2D横版射击游戏相关推荐

  1. Unity 4 3 制作一个2D横版射击游戏 2

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! 在上一篇 ...

  2. Unity 4.3 制作一个2D横版射击游戏(2)

    在上一篇<Unity 4.3 制作一个2D横版射击游戏>时,已经完成一个基本的射击游戏了.在这一篇将继续完善. 1.视差卷轴效果 为了达到这种视差卷轴的效果,可以让背景层以不同的速度进行移 ...

  3. Unity 4.3 制作一个2D横版射击游戏

    这是一个横版射击游戏. 教程来自: http://pixelnest.io/tutorials/2d-game-unity/   中文版教程: http://www.litpo.com/categor ...

  4. Unity3D开发一个2D横版射击游戏

    教程基于http://pixelnest.io/tutorials/2d-game-unity/ , 这个例子感觉还是比较经典的, 网上转载的也比较多. 刚好最近也在学习U3D, 做的过程中自己又修改 ...

  5. Unity学习笔记3 简易2D横版RPG游戏制作(三)

    这一篇本来应该是在上一篇后面直接补进去的.不过因为排版的问题.所以我就另开一篇来整理了,好了,废话不多说,马上整理: 十八.关卡的锁定与解锁 前面我们已经解决了在游戏开始时可以选择关卡的问题,接下来我 ...

  6. unity3d游戏2d横版射击游戏完整项目源码分享

    unity3d游戏2d横版射击游戏完整项目源码分享 免费下载地址: 链接:https://pan.baidu.com/s/1YwhEy7DeKIHFU8pBLdJFPg 提取码:3wnx 复制这段内容 ...

  7. Unity学习笔记1 简易2D横版RPG游戏制作(一)

    这个教程是参考一个YouTube上面的教程做的,原作者的教程做得比较简单,我先参考着做一遍,毕竟我也只是个初学者,还没办法完全自制哈哈.不过我之前也看过一个2D平台游戏的系列教程了,以后会整合起来,做 ...

  8. Unity学习笔记2 简易2D横版RPG游戏制作(二)

    十二.敌人受攻击时的闪烁和Player的生命值的修正 上一篇中,我们利用Controller2D中的IEnumerator TakenDamage接口,使得我们的Player受到攻击时会进行闪烁,我们 ...

  9. 【CSON原创】基于HTML5的横版射击游戏发布

    功能说明: 基于HTML5的横版射击游戏,参考自flash游戏<双面特工>.左右方向键控制移动,下方向键蹲下,上方向键跳跃,空格键射击.体验前请先关闭输入法. 该游戏基于自己开发的HTML ...

最新文章

  1. CSS结构选择器四种结构关系的范围
  2. iOS11和iPhone X的适配
  3. 通俗易懂的图解堆排序
  4. React开发(199):参数请求错误修改请求
  5. java 字符查找 截断_java字符串常用操作(查找、截取、分割)
  6. 一加9 Pro真机图曝光:哈苏相机联名logo助力影像旗舰
  7. java双机和集群的区别,java 分布式与集群的区别和联系
  8. hooks taro 下拉刷新_Hooks
  9. docker运行jenkins挂掉_docker搭建jenkins
  10. Arduino+sim800 gsm收发短信
  11. 单例模式详解(线程安全,饿汉,懒汉模式)
  12. Rayman的绝顶之路——Leetcode每日一题打卡20
  13. 【MatLab fdatool】Butterworth 低通 带阻 滤波器 (MatLab C++)
  14. 世界杯最野蛮大战,巴西付出慘重代价步入四强
  15. 被遗忘的数学家!曾提出最接地气的数学定理,可以计算男朋友真不真心的那种......
  16. 从零到百亿互网融构展
  17. Cocos实战案例:高手解析《捕鱼达人3》怎样玩3D
  18. 2019年互联网公司月饼颜值大比拼!
  19. vue 移动端头像裁剪_移动端 上传头像 并裁剪功能(h5)
  20. 基本:HEX文件格式定义

热门文章

  1. CentOS上快速安装Oracle服务器脚本
  2. Oracle数据库之间数据同步 -- DBLink
  3. 解决小程序图片在开发者工具能显示,测试时真机不显示问题
  4. Android udp json+数组 ---gt;bytes发送数据
  5. docker随着主机启动 自动启动设置
  6. okHttp记录---response.body().string()输出的结构是乱码
  7. 阿里前端开源的一些产品
  8. mvp内粗泄露问题_如何在一小时内启动MVP服务器
  9. 错过校招_您可能错过的Web优化技巧
  10. C++ 学习笔记---零散的基础知识