赞
踩
展示链接:打靶子(ShootTarget)_网络游戏热门视频
源码链接:传送门
玩家将操控十字弩在游戏场景中移动,如果移动到了指定场景,玩家可以通过点击鼠标左键蓄力射出弓箭,当弓箭射中靶子之后,玩家可以获得相应的分数。值得注意的是,每个指定位置可以使用的弓箭的数量是有限的,当箭被射完后,玩家将无法再射箭。按R键可以重置游戏。
在层级选项卡中点击鼠标右键,选中3D对象,找到并创建地形
选中创建的地形,在检查器中找到Terrain属性,将这个位置调整为Raise or Lower Terrain
然后使用笔刷在画面中点点画画,以创造不同的地形
然后在检查器中找到Terrain属性,将这个位置调整为Paint Texture,选择编辑地形层,然后导入图片材料
在绘制好的地形上的不同位置涂上不同的图片。
选中创建的地形,在检查器中找到Terrain属性,选择箭头所指的绘制树,再点击编辑树以导入树的预制体,然后在地形上画出预制体即可。
和生成树一样。
创建一个空对象,然后在空对象中创建五个圆柱体,5个圆柱体数据如下:
记得给每个圆柱体加上Mesh Collider的碰撞组件。
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
-
- public class ChangeSky : MonoBehaviour
- {
- public Material[] skyboxMaterials;
- int index;
- // Start is called before the first frame update
- void Start()
- {
- index = skyboxMaterials.Length - 1;
- StartCoroutine(ChangeSkyBox());
- }
-
- IEnumerator ChangeSkyBox()
- {
- while (true)
- {
- // 随机选择一个天空盒子材质
- index = (index + 1) % skyboxMaterials.Length;
- RenderSettings.skybox = skyboxMaterials[index];
-
- // 等待一段时间后再切换天空盒子
- yield return new WaitForSeconds(10);
- }
- }
- }
- using System.Collections.Generic;
- using Unity.VisualScripting;
- using UnityEngine;
-
- public class TargetGenerator : MonoBehaviour
- {
- public GameObject targetPrefab; // 目标对象的预制体
- public GameObject shootAreaPrefab; // 设计区域预制体
- public int numberOfTargets = 6; // 要生成的目标数量
- public int ArrowCount = 6;
- public List<int> arrows = new List<int>();
-
- void Start()
- {
- GenerateTargets();
- }
-
- void GenerateTargets()
- {
- for (int i = 0; i < numberOfTargets; i++)
- {
- // 随机生成目标的位置
- Vector3 randomPosition;
-
- randomPosition = new Vector3((i + 1) * 10 + Random.Range(-2.5f, 2.5f) - 60, Random.Range(2f, 2.5f), Random.Range(-17f, 3f));
-
- // 使用预制体在随机位置生成目标
- GameObject target = Instantiate(targetPrefab, randomPosition, Quaternion.identity);
-
- GameObject shootArea = Instantiate(shootAreaPrefab, new Vector3(randomPosition.x, 0, randomPosition.z - 15f), Quaternion.identity);
-
- // 设置目标的名称
- target.name = "Target" + (i + 1);
-
- shootArea.name = "ShootArea" + (i + 1);
-
- if(i % 2 != 0)
- {
- // 添加 Animator 组件并设置动画控制器
- Animator targetAnimator = target.GetComponent<Animator>();
- if (targetAnimator != null)
- {
- // 这里假设你有一个名为 "TargetController" 的动画控制器
- if(i == 1)
- {
- targetAnimator.runtimeAnimatorController = Resources.Load<RuntimeAnimatorController>("Animation/Target");
- shootArea.transform.position = new Vector3(0, 0, -14f);
- }else if(i == 3)
- {
- targetAnimator.runtimeAnimatorController = Resources.Load<RuntimeAnimatorController>("Animation/Target1");
- shootArea.transform.position = new Vector3(25f, 0, -7f);
- }
- else
- {
- targetAnimator.runtimeAnimatorController = Resources.Load<RuntimeAnimatorController>("Animation/Target2");
- shootArea.transform.position = new Vector3(10f, 0, -16f);
- }
-
- }
- }
- arrows.Add(ArrowCount);
- }
- }
-
- // 调用这个函数来删除指定标签的游戏对象
- private void DeleteObjectsWithLabel(string label)
- {
- // 获取场景中所有的游戏对象
- GameObject[] allObjects = GameObject.FindObjectsOfType<GameObject>();
-
- // 遍历游戏对象数组
- foreach (GameObject obj in allObjects)
- {
- // 检查游戏对象是否有标签,并且标签匹配
- if (obj.CompareTag(label))
- {
- // 删除游戏对象
- Destroy(obj);
- }
- }
- }
-
- public void Reset()
- {
- arrows.Clear();
- DeleteObjectsWithLabel("Target");
- DeleteObjectsWithLabel("ShootArea");
- GenerateTargets();
- }
-
- }
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
-
- public class CrossbowMove : MonoBehaviour
- {
- Camera cam;
- CharacterController playerController;
-
- Vector3 direction;
-
- public float speed = 5;
- public float jumpPower = 3;
- public float gravity = 9.8f;
- public float mousespeed = 10f;
-
- public float minmouseY = -45f;
- public float maxmouseY = 45f;
-
- float RotationY = 0f;
- float RotationX = 0f;
-
- float time;
-
- bool canShoot = false;
-
- int pos = -1;
-
- // Start is called before the first frame update
- void Awake()
- {
- cam = Camera.main;
- cam.transform.parent = this.transform;
- cam.transform.localPosition = new Vector3(0, 1, 0);
- cam.transform.localRotation = Quaternion.Euler(45, 0, 0);
- playerController = this.GetComponent<CharacterController>();
- canShoot = false;
- }
-
- // Update is called once per frame
- void Update()
- {
- HandleRotationInput();
-
- // Handle ground movement and jumping
- if (IsGrounded())
- {
- HandleGroundMovement();
- }
-
- ApplyGravity();
-
- // Move the player
- playerController.Move(direction * Time.deltaTime * speed);
-
- // Shoot
- Shoot();
- }
-
- void HandleRotationInput()
- {
- float mouseX = Input.GetAxis("Mouse X") * mousespeed;
- float mouseY = -Input.GetAxis("Mouse Y") * mousespeed; // Inverted for more intuitive camera control
-
- RotationX += mouseX;
- RotationY = Mathf.Clamp(RotationY + mouseY, minmouseY, maxmouseY);
-
- // Apply rotation using Quaternion
- transform.rotation = Quaternion.Euler(RotationY, RotationX, 0);
- cam.transform.localRotation = Quaternion.Euler(RotationY / 4, 0, 0);
- }
-
- bool IsGrounded()
- {
- float raycastDistance = 5f; // 调整为适当的值
- float characterHeight = 1.1f; // 角色的高度,调整为适当的值
-
- // 发射射线向下检测地面
- if (Physics.Raycast(transform.position, Vector3.down, out RaycastHit hit, raycastDistance))
- {
- // 计算地面和角色的高度差
- float groundHeight = hit.point.y;
- float heightDifference = transform.position.y - groundHeight;
-
- // 如果高度差小于等于角色高度的一半,则认为角色在地面上
- return heightDifference <= characterHeight;
- }
-
- // 如果射线未击中地面,则认为角色不在地面上
- return false;
- }
-
- void HandleGroundMovement()
- {
- float horizontal = Input.GetAxis("Horizontal");
- float vertical = Input.GetAxis("Vertical");
-
- // Calculate movement direction based on rotation
- Vector3 forward = transform.forward;
- Vector3 right = transform.right;
-
- // Calculate movement input
- Vector3 moveDirection = horizontal * right + vertical * forward;
- moveDirection.Normalize();
-
- // Jumping
- if (Input.GetKeyDown(KeyCode.Space))
- {
- moveDirection.y = jumpPower;
- }
-
- // Set the direction
- direction = moveDirection;
- }
-
- void ApplyGravity()
- {
- // Apply gravity
- direction.y -= gravity * Time.deltaTime;
- }
-
- void Shoot()
- {
- TargetGenerator t = FindObjectOfType<TargetGenerator>();
- if (canShoot && t.arrows[pos] > 0)
- {
- View view = FindObjectOfType<View>();
- if (Input.GetMouseButtonDown(0))
- {
- time = 0;
- }
- else if (Input.GetMouseButton(0))
- {
- time += Time.deltaTime;
- float power = Mathf.Clamp01(GetComponent<Animator>().GetFloat("Power") + time / 100);
- GetComponent<Animator>().SetFloat("Power", power);
- view.UpdatePower(power);
- }
- else if (Input.GetMouseButtonUp(0))
- {
- GetComponent<Animator>().SetTrigger("Shoot");
- GetComponent<Animator>().SetFloat("Power", 0.5f);
- view.UpdatePower(0f);
- // Instantiate arrow with a slight offset in the Y-axis
- GameObject arrowPrefab = Resources.Load<GameObject>("Prefabs/Arrow");
- Vector3 arrowSpawnPosition = transform.position + new Vector3(0, 1.0f, 0); // Adjust the Y-axis offset
- GameObject arrow = Instantiate(arrowPrefab, arrowSpawnPosition, transform.rotation);
- GameObject subCamPrefab = Resources.Load<GameObject>("Prefabs/subCamera");
- Vector3 subCamSpawnPosition = arrow.transform.position + new Vector3(0, 0.2f, -0.5f);
- Quaternion rotation = Quaternion.Euler(0, 0, 0);
- GameObject subCam = Instantiate(subCamPrefab, subCamSpawnPosition, rotation);
- subCam.transform.SetParent(arrow.transform);
-
- // Add Rigidbody component to the arrow
- Rigidbody arrowRigidbody = arrow.GetComponent<Rigidbody>();
-
- // Set velocity to the arrow based on the character's forward direction and power
- float arrowSpeed = Mathf.Min(10.0f + time * 5, 20f); // Adjust the speed as needed
- arrowRigidbody.velocity = transform.forward * arrowSpeed;
- t.arrows[pos]--;
- }
- }
- }
-
- private void OnTriggerStay(Collider other)
- {
- if (other.CompareTag("ShootArea"))
- {
- // 获取碰撞的具体圆柱体名称
- string shootAreaName = other.name.Substring("ShootArea".Length);
-
- // 提取圆柱体名称中的数字
- int shootAreaNumber;
- if (int.TryParse(shootAreaName, out shootAreaNumber))
- {
- pos = shootAreaNumber - 1;
- }
- canShoot = true;
- View view = FindObjectOfType<View>();
- TargetGenerator t = FindObjectOfType<TargetGenerator>();
- view.UpdateShoot(canShoot);
- view.UpdateArrowCount(t.arrows[pos]);
- }
- }
-
- private void OnTriggerExit(Collider other)
- {
- if (other.CompareTag("ShootArea"))
- {
- pos = -1;
- canShoot = false;
- View view = FindObjectOfType<View>();
- view.UpdateShoot(canShoot);
- }
- }
-
- }
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
- using UnityEngine.Windows.WebCam;
-
- public class ArrowBehavior : MonoBehaviour
- {
- private bool isFixed = false; // 用于标记箭是否已经固定在胶囊体上
-
- private void OnCollisionStay(Collision collision)
- {
- if (!isFixed)
- {
- // 检测碰撞对象是否是圆柱体
- if (collision.collider.CompareTag("Target"))
- {
- // 获取碰撞的具体圆柱体名称
- string cylinderName = collision.collider.name;
-
- // 提取圆柱体名称中的数字
- int cylinderNumber;
- if (int.TryParse(cylinderName, out cylinderNumber))
- {
- // 在这里可以根据具体的圆柱体编号执行相应的逻辑
- Debug.Log("Arrow hit capsule: " + cylinderNumber);
-
- transform.SetParent(collision.transform.parent.transform);
-
- // 固定箭在圆柱体上
- FixArrowToCapsule(collision.contacts[0].point);
- StartCoroutine(DisableSubCamAfterDelay(transform.GetChild(3).gameObject, 2.0f));
-
- // 获取记分系统并调用加分方法
- ScoreManager scoreManager = FindObjectOfType<ScoreManager>();
- View view = FindObjectOfType<View>();
- if (scoreManager != null)
- {
- string TargetName = collision.transform.parent.name.Substring("Target".Length);
- int TargetNumber;
- if (int.TryParse(TargetName, out TargetNumber))
- {
- if(TargetNumber %2 == 0)
- {
- scoreManager.IncreaseScore(cylinderNumber + TargetNumber);
- }
- else
- {
- scoreManager.IncreaseScore(cylinderNumber);
- }
- view.UpdateScore(scoreManager.score);
- view.UpdateMaxScore(scoreManager.score);
- view.AddHitTarget(collision.transform.parent.name, cylinderNumber);
- }
- }
-
- }
- }
- else if (collision.transform.name == "Ground")
- {
- Destroy(this.gameObject);
- }
- }
- }
-
- private void FixArrowToCapsule(Vector3 contactPoint)
- {
- // 固定标记设为 true
- isFixed = true;
-
- // 可以执行其他固定逻辑,例如禁用箭的 Rigidbody 组件等
- Rigidbody arrowRigidbody = GetComponent<Rigidbody>();
- if (arrowRigidbody != null)
- {
- arrowRigidbody.isKinematic = true; // 禁用 Rigidbody 的运动
- }
-
- // 将箭的位置调整到碰撞点
- transform.GetChild(2).position = contactPoint;
-
- transform.GetChild(1).gameObject.SetActive(false);
-
- transform.rotation = Quaternion.identity;
- }
-
- private IEnumerator DisableSubCamAfterDelay(GameObject subCam, float delay)
- {
- yield return new WaitForSeconds(delay);
-
- // 禁用subCam
- subCam.gameObject.SetActive(false);
- }
-
- }
- using UnityEngine;
-
- public class ScoreManager : MonoBehaviour
- {
- public int score;
-
- public ScoreManager()
- {
- score = 0;
- }
-
- public void IncreaseScore(int s)
- {
- // 箭射中目标,增加分数
- score += s;
- }
-
- public void Reset()
- {
- score = 0;
- }
- }
界面View.cs
- using System.Collections;
- using System.Collections.Generic;
- using UnityEditor;
- using UnityEngine;
-
- public class View : MonoBehaviour
- {
- private int score = 0;
- private float power = 0.0f;
- private float maxPower = 1.0f;
- private bool shoot = false;
- private int arrowCount = 6;
- private int maxScore = 0;
-
- // 记录击中箭靶的列表
- private List<string> hitTargets = new List<string>();
- private List<int> hitPoints = new List<int>();
-
- // 用于滚动的位置
- private Vector2 scrollPosition = Vector2.zero;
-
- private void OnGUI()
- {
- // 设置GUI样式
- GUIStyle style = new GUIStyle();
- style.fontSize = 24; // 设置默认字体大小
- style.normal.textColor = Color.black;
-
- // 显示分数
- GUI.Label(new Rect(10, 10, 200, 30), "得分: " + score, style);
-
- // 显示最高分数
- GUI.Label(new Rect(120, 10, 200, 30), "最高分: " + maxScore, style);
-
- // 显示蓄力条
- DrawPowerBar();
-
- // 绘制红点在屏幕中央
- float dotSize = 10f;
- float dotPositionX = Screen.width / 2 - dotSize / 2;
- float dotPositionY = Screen.height / 2 - dotSize / 2;
-
- Texture2D redDotTexture = new Texture2D(1, 1);
- redDotTexture.SetPixel(0, 0, Color.red);
- redDotTexture.Apply();
-
- GUI.DrawTexture(new Rect(dotPositionX, dotPositionY, dotSize, dotSize), redDotTexture);
-
- // 重置游戏
- GUI.Label(new Rect(Screen.width - 210, Screen.height - 55, 200, 30), "按R键重置游戏", style);
-
- // 设置列表的位置和大小
- float listPositionX = 10f;
- float listPositionY = 60f;
- float listItemHeight = 20f; // 设置列表项默认高度
- float listHeight = 8 * listItemHeight; // 固定列表高度,超过这个高度将出现滚动条
-
- // 使用ScrollView实现滚动
- scrollPosition = GUI.BeginScrollView(new Rect(listPositionX, listPositionY, 200, listHeight), scrollPosition, new Rect(0, 0, 200, hitTargets.Count * listItemHeight));
-
- // 遍历击中箭靶的列表,并显示记录
- for (int i = 0; i < hitTargets.Count; i++)
- {
- // 设置记录的字体大小为16
- GUIStyle recordStyle = new GUIStyle(style);
- recordStyle.fontSize = 16;
- recordStyle.normal.textColor = Color.black;
- GUI.Label(new Rect(0, i * listItemHeight, 200, listItemHeight), "恭喜射中" + hitTargets[i] + "的" + hitPoints[i] + "环", recordStyle);
- }
-
- // 结束ScrollView
- GUI.EndScrollView();
-
- if (!shoot)
- {
- // 设置字体
- GUIStyle shootStyle = new GUIStyle(style);
- shootStyle.fontSize = 16;
- shootStyle.normal.textColor = Color.red;
- GUI.Label(new Rect(10, Screen.height - 30f, 90.0f, 30.0f), "您现在不能射击,请前往指定区域", shootStyle);
- }
- else
- {
- // 设置字体
- GUIStyle shootStyle = new GUIStyle(style);
- shootStyle.fontSize = 16;
- shootStyle.normal.textColor = Color.magenta;
- GUI.Label(new Rect(10, Screen.height - 30f, 90.0f, 30.0f), "您现在能射击了!!!", shootStyle);
- shootStyle.normal.textColor = Color.yellow;
- GUI.Label(new Rect(Screen.width / 2 - 45.0f, 30.0f, 90.0f, 30.0f), "此处还剩箭:" + arrowCount + "只", shootStyle);
- }
- }
-
- // 提供一个方法用于更新分数
- public void UpdateScore(int newScore)
- {
- score = newScore;
- }
-
- public void UpdateMaxScore(int newScore)
- {
- if(score > maxScore)
- {
- maxScore = score;
- }
- }
-
- public void UpdatePower(float newPower)
- {
- power = newPower;
- }
-
- public void UpdateShoot(bool newShoot)
- {
- shoot = newShoot;
- }
-
- public void UpdateArrowCount(int newArrowCount)
- {
- arrowCount = newArrowCount;
- }
-
- // 添加箭靶击中记录
- public void AddHitTarget(string targetName,int hitpos)
- {
- hitTargets.Add(targetName);
- hitPoints.Add(hitpos);
- }
-
- // 绘制蓄力条
- private void DrawPowerBar()
- {
- float barLength = 200f;
- float barHeight = 20f;
- float barPositionX = (Screen.width - barLength) - 10;
- float barPositionY = Screen.height - barHeight - 5;
-
- // 绘制蓄力条的背景
- GUI.Box(new Rect(barPositionX, barPositionY, barLength, barHeight), "Power");
-
- // 计算蓄力条的填充比例
- float fillRatio = power / maxPower;
-
- // 绘制蓄力条的填充部分
- GUI.Box(new Rect(barPositionX, barPositionY, barLength * fillRatio, barHeight), GUIContent.none);
- }
-
- public void Reset()
- {
- score = 0;
- power = 0;
- maxPower = 1.0f;
- shoot = false;
- arrowCount = 6;
- hitTargets.Clear();
- hitPoints.Clear();
- scrollPosition = Vector2.zero;
- }
- }
- using UnityEngine;
-
- public class ResetManager : MonoBehaviour
- {
- // 引用View、ScoreManager和TargetGenerator脚本
- private View view;
- private ScoreManager scoreManager;
- private TargetGenerator targetGenerator;
-
- private void Awake()
- {
- view = FindObjectOfType<View>();
- scoreManager = FindObjectOfType<ScoreManager>();
- targetGenerator = FindObjectOfType<TargetGenerator>();
- }
-
- void Update()
- {
- // 当按下R键时触发Reset函数
- if (Input.GetKeyDown(KeyCode.R))
- {
- // 调用View.cs中的Reset函数
- if (view != null)
- {
- view.Reset();
- }
-
- // 调用ScoreManager.cs中的Reset函数
- if (scoreManager != null)
- {
- scoreManager.Reset();
- }
-
- // 调用TargetGenerator.cs中的Reset函数
- if (targetGenerator != null)
- {
- targetGenerator.Reset();
- }
- }
- }
- }
CTRL+6唤出动画选项卡
选中要添加动画的游戏对象,编辑即可
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。