Unity3D 从入门到放弃(五)
—-射箭游戏
填坑啊填坑,每周都补上周作业,啥时候才能到头啊= =
作业需求
游戏规则:
设计一个射箭小游戏,点击鼠标射箭:
靶对象为 5 环,按环计分;
箭对象,射中后要插在靶上;
游戏仅一轮,无限 trials;
实例化部分
本次作业有箭,靶两种实例,实现如下:
箭:
箭分为三个部分,箭头,箭身,箭尾。
箭头:通过一个圆锥和一个圆来实现。圆可以由高度为0的圆锥生成。箭头加上Mesh碰撞器并设置为触发器。(圆锥可以通过Editor文件夹中的CreateCone中创造的菜单实现)
箭身:通过一个圆柱来实现。
箭尾:通过两个双面四边形实现,由于unity3d默认渲染单面,因此要四个。(四边形可以通过Editor文件夹中的CreateRectangle中创造的菜单实现)
为了添加重力,箭总体加入一个刚体。
最后,将制作好的箭加入预设,作为初始物体。靶:
制作六个圆柱体,分别上不同颜色,并将内圈scale.Y的大小稍微调大一点以显示颜色,调整好角度,加上Mesh碰撞器即可。文字框:
通过UI中的Text创建文字框,此处不再阐述。
效果如图:
箭:
靶:
打地基部分:
由于这次用的圆锥和四边形都不是unity3d自带的结构,因此需要自己创造。
首先,先创建一个Editor文件夹:(unity3d默认在Editor文件夹中的内容不能挂载,用于实现一些自动调用的脚本)
然后,在文件夹内添加CreateCone和CreateRectangle脚本:
脚本内容如下:
CreateCone:
/*
* 描 述:用于创建圆锥的文件,我只是大自然的搬运工
* 作 者:hza
* 创建时间:2017/04/06 13:20:14
* 版 本:v 1.0
*/
using UnityEngine;
using UnityEditor;
using System.Collections;
public class CreateCone : ScriptableWizard
{
/**
* Num Vertices is the number of vertices each end will have.
* Radius Top is the radius at the top. The center point will be located at (0/0/0).
* Radius Bottom is the radius at the bottom. The center point will be located at (0/0/Length).(底圆的半径大小)
* Length is the number of world units long the plane will be (+Z direction).
* Opening Angle If this is >0, the top radius is set to 0, and the bottom radius is computed depending on the length, so that the given opening angle is created.(貌似是底圆是多少边形,即越大越接近圆形)
* Outside defines whether the outside is visible (default).
* Inside defines whether the inside is visible. Set both outside and inside to create a double-sided primitive.
* Add Collider creates a matching mesh collider for the cone if checked.
*/
public int numVertices = 10;
public float radiusTop = 0f;
public float radiusBottom = 1f;
public float length = 1f;
public float openingAngle = 0f; // if >0, create a cone with this angle by setting radiusTop to 0, and adjust radiusBottom according to length;
public bool outside = true;
public bool inside = false;
public bool addCollider = false;
[MenuItem("GameObject/Create Other/Cone")]
static void CreateWizard()
{
ScriptableWizard.DisplayWizard("Create Cone", typeof(CreateCone));
}
void OnWizardCreate()
{
GameObject newCone = new GameObject("Cone");
if (openingAngle > 0 && openingAngle < 180)
{
radiusTop = 0;
radiusBottom = length * Mathf.Tan(openingAngle * Mathf.Deg2Rad / 2);
}
string meshName = newCone.name + numVertices + "v" + radiusTop + "t" + radiusBottom + "b" + length + "l" + length + (outside ? "o" : "") + (inside ? "i" : "");
string meshPrefabPath = "Assets/Editor/" + meshName + ".asset";
Mesh mesh = (Mesh)AssetDatabase.LoadAssetAtPath(meshPrefabPath, typeof(Mesh));
if (mesh == null)
{
mesh = new Mesh();
mesh.name = meshName;
// can't access Camera.current
//newCone.transform.position = Camera.current.transform.position + Camera.current.transform.forward * 5.0f;
int multiplier = (outside ? 1 : 0) + (inside ? 1 : 0);
int offset = (outside && inside ? 2 * numVertices : 0);
Vector3[] vertices = new Vector3[2 * multiplier * numVertices]; // 0..n-1: top, n..2n-1: bottom
Vector3[] normals = new Vector3[2 * multiplier * numVertices];
Vector2[] uvs = new Vector2[2 * multiplier * numVertices];
int[] tris;
float slope = Mathf.Atan((radiusBottom - radiusTop) / length); // (rad difference)/height
float slopeSin = Mathf.Sin(slope);
float slopeCos = Mathf.Cos(slope);
int i;
for (i = 0; i < numVertices; i++)
{
float angle = 2 * Mathf.PI * i / numVertices;
float angleSin = Mathf.Sin(angle);
float angleCos = Mathf.Cos(angle);
float angleHalf = 2 * Mathf.PI * (i + 0.5f) / numVertices; // for degenerated normals at cone tips
float angleHalfSin = Mathf.Sin(angleHalf);
float angleHalfCos = Mathf.Cos(angleHalf);
vertices[i] = new Vector3(radiusTop * angleCos, radiusTop * angleSin, 0);
vertices[i + numVertices] = new Vector3(radiusBottom * angleCos, radiusBottom * angleSin, length);
if (radiusTop == 0)
normals[i] = new Vector3(angleHalfCos * slopeCos, angleHalfSin * slopeCos, -slopeSin);
else
normals[i] = new Vector3(angleCos * slopeCos, angleSin * slopeCos, -slopeSin);
if (radiusBottom == 0)
normals[i + numVertices] = new Vector3(angleHalfCos * slopeCos, angleHalfSin * slopeCos, -slopeSin);
else
normals[i + numVertices] = new Vector3(angleCos * slopeCos, angleSin * slopeCos, -slopeSin);
uvs[i] = new Vector2(1.0f * i / numVertices, 1);
uvs[i + numVertices] = new Vector2(1.0f * i / numVertices, 0);
if (outside && inside)
{
// vertices and uvs are identical on inside and outside, so just copy
vertices[i + 2 * numVertices] = vertices[i];
vertices[i + 3 * numVertices] = vertices[i + numVertices];
uvs[i + 2 * numVertices] = uvs[i];
uvs[i + 3 * numVertices] = uvs[i + numVertices];
}
if (inside)
{
// invert normals
normals[i + offset] = -normals[i];
normals[i + numVertices + offset] = -normals[i + numVertices];
}
}
mesh.vertices = vertices;
mesh.normals = normals;
mesh.uv = uvs;
// create triangles
// here we need to take care of point order, depending on inside and outside
int cnt = 0;
if (radiusTop == 0)
{
// top cone
tris = new int[numVertices * 3 * multiplier];
if (outside)
for (i = 0; i < numVertices; i++)
{
tris[cnt++] = i + numVertices;
tris[cnt++] = i;
if (i == numVertices - 1)