种田RPG游戏(一)

游戏角色

一、导入资源

1、获取资源动画人物

2、创建项目

3、导入资源:人物、走、跑、休息

(1) 新建文件夹。Import Asset

(2) 将资源导入

二、设置人物

1、新建场景。Farm

2、增加角色,命名为Player

3、点击Import Asset中的角色,选中材质

4、点击Extract Textures,在弹出框点击“选择”。在弹出框中选择Fix Now

5、再次点击Import Asset中的角色,选中Rig,将Animation Type设置为Humanoid

6、将Avatar Definetion 设置为Create From This Model,apply

7、设置Walking、Running和Idle

8、新建Prefabs文件夹,将角色制成预制体

9、设置摄像机

三、设置人物动画

1、新建文件夹Animation,在Animation文件夹下新建文件夹Controllers

2、在Controller文件夹下Create Animator Controller,命名为Player

3、选中Hierarchy中的人物,在Inspector面板中给Animator中的Controller选择Player

4、打开Controller文件夹下的Player,此时还没有动画

5、找到Walking、Running和Idle的资源,点击右侧小三角,复制mixano.com,分别重命名为Walking、Running和Idle,将复制的Walking、Running和Idle转移到Animation文件夹

6、分别选择Walking、Running和Idle,设置循环播放(Loop Pose也勾选上)

7、打开Controller文件夹下的Player,依次将Idle(默认)、Walking、Running拖入新界面

8、选择Parameters,依次添加Float和Bool,分别命名为Speed和Running,

调节三者的Speed值(步伐快慢)一般与脚本设置的Speed一致

9、设置条件,选中Idle,右击,选择Make Transition,单击Walking

10、选中Idle到Walking的箭头,添加Conditons,设置Speed的Greater为0.001(当速度大于0.001时行走)这个可以参照角色添加的组件中的Min Move Distance(改为0.01)

取消勾选Has Exit Time

11、选中Walking,右击,选择Make Transition,单击Idle

12、选中Walking到Idle的箭头,添加Conditons,设置Speed的less为0.001(速度小于0.001时站立 ),取消勾选Has Exit Time。这一步的数值需要反复调整

四、控制人物行走

1、给人物预制体,添加Character Controller(角色控制器)组件,调节参数至笼罩全身

2、新建文件夹Scripts,给人物预制体添加PlayerController.cs组件

public class PlayerController : MonoBehaviour
{
    private CharacterController controller;
    private Animator animator; 
    void Start()
    {
        controller = GetComponent<CharacterController>();
        animator = GetComponent<Animator>();
    }

    void Update()
    {
        Move();
    }

    public void Move()
    {
        
    }
}

3、回到Unity-Edit-Projects Setting-Input Manager,观察水平和垂直方向上字母的写法

4、打开PlayerController.cs,设定角色行走

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerController : MonoBehaviour
{
    private CharacterController controller;
    private Animator animator;

    private float moveSpeed=2f;
    void Start()
    {
        controller = GetComponent<CharacterController>();
        animator = GetComponent<Animator>();
    }

    void Update()
    {
        Move();
    }

    public void Move()
    {
        float horizontal = Input.GetAxisRaw("Horizontal");
        float vertical = Input.GetAxisRaw("Vertical");

        Vector3 dir = new Vector3(horizontal, 0, vertical).normalized;
        Vector3 velocity = moveSpeed * Time.deltaTime * dir;

        if (dir.magnitude > 0.1f)
        {
            //朝向哪个方向
            transform.rotation =Quaternion.LookRotation(dir);//测试一下
            //运动
            controller.Move(velocity);
        }
    }
}

 几点说明

(1) Input.GetAxisRaw("Horizontal")

作用

精确地控制输入(如在一个物理模拟中),或想完全避免Unity的平滑处理

解析

Input.GetAxis("Horizontal") :平滑的角色移动或摄像机旋转效果

通过Unity的 Input Manager(输入管理器)自定义轴的行为和敏感度,会影响到GetAxisGetAxisRaw的行为。

例如,改变轴的死区(deadzone),以减少轻微的输入波动。

这些设置可以在Unity的编辑器中的"Edit" -> "Project Settings" -> "Input"菜单下找到

(2) if(dir.magnitude > 0.1f) :

作用

检查 dir 的长度是否大于0.1,判断用户输入是否足够显著,从而防止因玩家手部的微小移动或设备的噪声而导致的误操作

解析

dir.magnitude 

计算这个向量长度(或模)的属性。

Vector3 下:计算的是三维空间中从原点(0,0,0)到该向量所表示的点之间的欧几里得距离。

                     简单地说就是两点之间的直线长度

(3) CharacterController 组件

作用

用于处理角色(通常是第一人称或第三人称角色)在物理环境中的移动

详解

简化角色移动:与直接使用刚体(Rigidbody)和碰撞器(Collider)相比,CharacterController 提供了一个更简化的方式来处理角色的移动。它允许你直接设置角色的速度和位置,而无需担心物理计算的复杂性

支持楼梯和斜坡:能够自动处理角色在楼梯和斜坡上的移动,而无需额外的脚本代码。

碰撞检测:提供了与场景中其他物体的碰撞检测功能。

                  可以通过监听 OnControllerColliderHit 事件来检测角色何时与另一个物体发生碰撞。

防止角色穿过墙壁: CharacterController 会处理角色与场景中的碰撞,

                                 可以确保角色不会穿过墙壁或其他障碍物

适用于非物理驱动的场景:若不希望角色受到物理引擎的完全控制(如在平台游戏中),CharacterController 提供了一个中间选项,允许你控制角色的移动,同时仍然受益于碰撞检测和防止穿透墙壁的功能

限制

不支持复杂的物理交互(如旋转力或扭矩),并且可能不适用于需要高度精确物理模拟的场景。

在这些情况下,一般需要使用刚体和碰撞器来替代 CharacterController

5、关联动画速度(注意Animator中的单词)与脚本的速度

public void Move()
{
    float horizontal = Input.GetAxis("Horizontal");
    float vertical = Input.GetAxis("Vertical");

    Vector3 dir = new Vector3(horizontal,0, vertical).normalized;
    Vector3 velocity = moveSpeed * Time.deltaTime * dir;

    if(dir.magnitude >0.1f)
    {
        transform.rotation= Quaternion.LookRotation(dir);
        controller.Move(velocity);
    }
    animator.SetFloat("Speed", velocity.magnitude);//新增。使animator的Speed与velocity.magnitude关联
}
五、控制奔跑

1、添加加速键

(1) Edit-Project Setting-Input Manager

(2) 更改Size由18改为19(增加一行)

(3) 选中新增行(最后一个Cancel)更改Name为Sprint,设置Positive Button为left shift,Alt Positive Button为 right shift

(4) 回到PlayerController.cs,设置加速(还不能奔跑)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerController : MonoBehaviour
{
    private CharacterController controller;
    private Animator animator;
    private float moveSpeed = 2f;

    //在Unity的Inspector面板显示标题
    [Header("Movement System")]
    public float walkSpeed = 2f;
    public float runSpeed = 4f;
    void Start()
    {
        controller = GetComponent<CharacterController>();
        animator = GetComponent<Animator>();
    }

    void Update()
    {
        Move();
    }
    public void Move()
    {
        float horizontal = Input.GetAxis("Horizontal");
        float vertical = Input.GetAxis("Vertical");

        Vector3 dir = new Vector3(horizontal, 0, vertical).normalized;
        Vector3 velocity = moveSpeed*Time.deltaTime*dir;

        //设置加速
        if (Input.GetButton("Sprint"))
        {
            moveSpeed = runSpeed;
        }
        else
        {
            moveSpeed = walkSpeed;
        }

        if(dir.magnitude > 0.1f)
        {
            transform.rotation = Quaternion.LookRotation(dir);
            controller.Move(velocity);
        }
        animator.SetFloat("Speed",velocity.magnitude);
    }
}

2、设置奔跑动画

(1) 设置动画:由步行到奔跑和奔跑到步行

(2) 回到PlayerController.cs,关联动画

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerController : MonoBehaviour
{
    private CharacterController controller;
    private Animator animator;
    private float moveSpeed = 2f;

    [Header("Movement System")]
    public float walkSpeed = 2f;
    public float runSpeed = 4f;
    void Start()
    {
        controller = GetComponent<CharacterController>();
        animator = GetComponent<Animator>();
    }

    void Update()
    {
        Move();
    }
    public void Move()
    {
        float horizontal = Input.GetAxis("Horizontal");
        float vertical = Input.GetAxis("Vertical");

        Vector3 dir = new Vector3(horizontal, 0, vertical).normalized;
        Vector3 velocity = moveSpeed*Time.deltaTime*dir;

        if (Input.GetButton("Sprint"))
        {
            moveSpeed = runSpeed;
            animator.SetBool("Running",true);//与动画关联
        }
        else
        {
            moveSpeed = walkSpeed;
            animator.SetBool("Running",false);//与动画关联
        }

        if(dir.magnitude > 0.1f)
        {
            transform.rotation = Quaternion.LookRotation(dir);
            controller.Move(velocity);
        }
        animator.SetFloat("Speed",velocity.magnitude);
    }
}

(3) 添加奔跑到Idle

六、相机跟随

1、Reset人物

2、调整相机的Transform

3、给Main Camera增加CameraController.cs组件(注意z轴的纵深)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CameraController : MonoBehaviour
{
    public float offsetz = 6f;
    Transform playerPos;
    void Start()
    {
        playerPos = FindObjectOfType<PlayerController>().transform;
    }

    void Update()
    {
        FollowPlayer();
    }
    void FollowPlayer()
    {
        Vector3 targerPos = new Vector3(playerPos.position.x, transform.position.y, playerPos.position.z-offsetz);
        transform.position = targerPos;
    }
}

4、增加平滑过渡效果

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CameraController : MonoBehaviour
{
    public float offsetz = 6f;
    public float smoothing = 8f;
    Transform playerPos;
    void Start()
    {
        playerPos = FindObjectOfType<PlayerController>().transform;
    }

    void Update()
    {
        FollowPlayer();
    }
    void FollowPlayer()
    {
        Vector3 targetPos = new Vector3(playerPos.position.x, transform.position.y, playerPos.position.z-offsetz);
        transform.position = Vector3.Lerp(transform.position, targetPos, smoothing*Time.deltaTime);
    }
}

Vector3.Lerp(transform.position, targetPos, smoothing*Time.deltaTime);

Vector3.Lerp :在两个Vector3值之间进行线性插值,

                           用于在物体的当前位置和目标位置之间平滑过渡

smoothing*Time.deltaTime :每帧移动的“进度”。

                                                控制过渡的平滑度和进度

好的,下面是个简单的种田游戏代码示例: ```python import random # 初始化玩家的金钱和种子数量 money = 1000 seed_count = 5 # 定义作物类 class Crop: def __init__(self, name, cost, time, income): self.name = name self.cost = cost self.time = time self.income = income def grow(self): self.time -= 1 def harvest(self): global money money += self.income print(f"你获得了 {self.income} 元金钱!") def is_ready(self): return self.time == 0 # 定义作物列表 crop_list = [ Crop("小麦", 100, 5, 200), Crop("玉米", 200, 10, 500), Crop("水稻", 300, 15, 800), ] # 游戏主循环 while True: # 打印玩家的状态 print(f"你现在有 {money} 元金钱和 {seed_count} 个种子。") # 让玩家选择要种植的作物 print("请选择要种植的作物:") for i, crop in enumerate(crop_list): print(f"{i + 1}. {crop.name}(单价:{crop.cost},成熟时间:{crop.time})") choice = input("请输入数字选择:") if choice.isdigit(): choice = int(choice) - 1 if choice >= 0 and choice < len(crop_list): crop = crop_list[choice] if money >= crop.cost and seed_count > 0: # 减少玩家的金钱和种子数量,种植作物 money -= crop.cost seed_count -= 1 print(f"你花费了 {crop.cost} 元金钱和个种子种植了 {crop.name}。") planted_crop = crop elif money < crop.cost: print("你没有足够的金钱购买这种作物!") else: print("你没有足够的种子!") else: print("选择无效!") else: print("选择无效!") # 让时间流逝,作物成长 days_passed = random.randint(1, 5) for i in range(days_passed): if planted_crop is not None: planted_crop.grow() if planted_crop.is_ready(): # 作物成熟,可以收割 print(f"{planted_crop.name} 成熟了!") planted_crop.harvest() planted_crop = None # 让玩家决定是否继续游戏 choice = input("输入 q 退出游戏,其他键继续:") if choice == "q": break print("游戏结束!") ``` 这个游戏比较简单,玩家可以选择要种植的作物,然后等待作物成长并收获。玩家可以在种田过程中赚取金钱,用于购买更多的种子和种植更多的作物。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值