农场游戏中的时间管理实例

news2024/11/16 13:22:48
一、准备工作

在Unity中创建承载日期和时间的文本

二、设置游戏的时间戳
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//标识这个类可以被序列化
[System.Serializable]
public class GameTimestamp
{
    // 游戏时间戳的成员变量
    public int year;
    //季节的枚举类型
    public enum Season { Spring, Summer, Fall, Winter }
    //星期几的枚举类型
    public enum DayOfTheWeek { Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday }
    public Season season;
    public int day;
    public int hour;
    public int minute;

    // 构造函数1:根据给定的参数创建一个游戏时间戳实例
    public GameTimestamp(int year, Season season, int day, int hour, int minute)
    {
        this.year = year;
        this.season = season;
        this.day = day;
        this.hour = hour;
        this.minute = minute;
    }
    
    // 构造函数2:复制给定的游戏时间戳实例
    public GameTimestamp(GameTimestamp timestamp)
    {
        this.year = timestamp.year;
        this.season = timestamp.season;
        this.day = timestamp.day;
        this.hour = timestamp.hour;
        this.minute = timestamp.minute;
    }
    
    // 更新游戏时钟
    public void UpdateClock()
    {
        minute++;

        if (minute >= 60) { minute = 0; hour++; }
        if (hour >= 24) { hour = 0; day++; }
        if (day > 30)
        {
            day = 1;
            if (season == Season.Winter) { season = Season.Spring; year++; }
            else { season++; }
        }
    }

    // 获得当天是星期几
    public DayOfTheWeek GetDayOfTheWeek()
    {
        int daysPassed = YearsToDays(year) + SeasonsToDays(season) + day;
        int dayIndex = daysPassed % 7;
        return (DayOfTheWeek)dayIndex;
    }

    // 将小时转换为分钟数
    public static int HoursToMinutes(int hour) { return hour * 60; }
    
    // 将天数转换为小时数
    public static int DaysToHours(int days) { return days * 24; }
    
    // 将季节转换为天数
    public static int SeasonsToDays(Season season)
    {
        int seasonIndex = (int)season;
        return seasonIndex * 30;
    }
    
    // 将年份转化为天数
    public static int YearsToDays(int year) { return year * 4 * 30; }

    // 比较两个不同的时间戳的差异
    public static int CompareTimestamp(GameTimestamp timestamp1, GameTimestamp timestamp2)
    {
        int timestamp1Hours = DaysToHours(YearsToDays(timestamp1.year)) + DaysToHours(SeasonsToDays(timestamp1.season) + DaysToHours(timestamp1.day) + timestamp1.hour);
        int timestamp2Hours = DaysToHours(YearsToDays(timestamp2.year)) + DaysToHours(SeasonsToDays(timestamp2.season) + DaysToHours(timestamp2.day) + timestamp2.hour);
        int difference = timestamp1Hours - timestamp2Hours;
        //返回 difference 的绝对值。
        //Mathf.Abs 是 Unity 引擎中的一个数学函数,用于计算一个数的绝对值。
        //在这个脚本中,它用于计算两个时间戳之间的差异,并返回一个非负值
        return Mathf.Abs(difference);
    }
}
三、设置时间流逝逻辑
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TimeManager : MonoBehaviour
{
    // 创建一个单例对象,其他脚本可以通过Instance访问
    public static TimeManager Instance { get; private set; }

    // 当脚本被实例化时调用的方法,用于初始化实例
    private void Awake()
    {
        // 如果Instance已经存在并且不等于当前实例,则销毁当前实例
        if (Instance != null && Instance != this) { Destroy(this); }
        else { Instance = this; }
    }
    //序列化字段
    [SerializeField]
    // 游戏的时间戳
    GameTimestamp timestamp;

    // 游戏的时间缩放比例(时间流逝速度)
    public float timeScale = 1.0f;

    // 游戏开始时调用的方法
    void Start()
    {
        // 初始化时间戳为游戏开始时的时间
        timestamp = new GameTimestamp(0, GameTimestamp.Season.Spring, 1, 6, 0);
        // 开始一个协程来更新游戏时间
        StartCoroutine(TimeUpdate());
    }
    // 游戏时间更新的协程
    IEnumerator TimeUpdate()
    {
        while (true)
        {
            // 每隔1 / timeScale秒执行一次Tick方法
            Tick();
            yield return new WaitForSeconds(1 / timeScale);
        }
    }
    // 每次游戏时间更新时调用的方法
    public void Tick()
    {
        // 更新时间戳
        timestamp.UpdateClock();
    }
}
四、日夜循环
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TimeManager : MonoBehaviour
{
    public static TimeManager Instance { get; private set; }
    private void Awake()
    {
        if (Instance != null && Instance != this) { Destroy(this); }
        else { Instance = this; }
    }

    [SerializeField]
    GameTimestamp timestamp;
    public float timeScale = 1.0f;
    //将一个用于表示白天和黑夜循环的Transform赋值给sunTransform变量,并声明一个ITimeTracker接口类型的列表listeners,用于保存所有注册的时间追踪器。
    [Header("Day and Night cycle")]
    public Transform sunTransform;
    List<ITimeTracker> listeners = new List<ITimeTracker>();

    void Start()
    {
        timestamp = new GameTimestamp(0, GameTimestamp.Season.Spring, 1, 6, 0);
        StartCoroutine(TimeUpdate());
    }
    IEnumerator TimeUpdate()
    {
        while (true)
        {
            Tick();
            yield return new WaitForSeconds(1 / timeScale);
        }
    }
    
    public void Tick()
    {
        //更新时间戳
        timestamp.UpdateClock();
        //通知所有注册的时间追踪器更新时间
        foreach (ITimeTracker listener in listeners)
        {
            listener.ClockUpdate(timestamp);
        }
        //调用UpdateSunMovement方法更新太阳的位置
        UpdateSunMovement();
    }

    void UpdateSunMovement()
    {
        //当前时间
        int timeInMinutes = GameTimestamp.HoursToMinutes(timestamp.hour) + timestamp.minute;
        //计算太阳的角度
        float sunAngle = .25f * timeInMinutes - 90;
        //将太阳角度应用到sunTransform的欧拉角上,实现太阳的运动
        sunTransform.eulerAngles = new Vector3(sunAngle, 0, 0);
    }

    //获取新的时间戳
    public GameTimestamp GetGameTimestamp()
    {
        //返回当前的时间戳
        return new GameTimestamp(timestamp);
    }
    //将一个时间追踪器注册到列表中
    public void RegisterTracker(ITimeTracker listener)
    {
        listeners.Add(listener);
    }
    //将一个时间追踪器从列表中移除
    public void UnregisterTracker(ITimeTracker listener)
    {
        listeners.Remove(listener);
    }
}
五、测试方法
public class PlayerController : MonoBehaviour

void Update()
{
    //测试光线逻辑
    if(Input.GetKey(KeyCode.RightBracket))
    {
        TimeManager.Instance.Tick();
    }
}

按住右方括号,加速时间流速

六、创建接口
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public interface ITimeTracker 
{
    void ClockUpdate(GameTimestamp timestamp);
}
七、显示游戏时间

1、编辑UIManager.cs,游戏时间

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

//添加接口,管理时间
public class UIManager : MonoBehaviour, ITimeTracker
{
    public static UIManager Instance { get; private set; }
    private void Awake()
    {
        if (Instance != null && Instance != this) { Destroy(this); }
        else { Instance = this; }
    }

    [Header("Startas Bar")]
    //手持工具栏中的时间文本
    public Text timeText;
    public Text dateText;

    private void Start()
    {
        //注册时间跟踪器(将UIManager添加到时间跟踪器的列表中)
        TimeManager.Instance.RegisterTracker(this);
    }

    //处理UI时间回调(回调:在特定的时刻执行自己定义的代码,实现特定的功能)
    //更新游戏中的时钟
    public void ClockUpdate(GameTimestamp timestamp)
    {
        //获取小时和分钟的值
        int hours = timestamp.hour;
        int minutes = timestamp.minute;

        string prefix = "AM ";
        //转换为下午的时间
        if (hours > 12)
        {
            prefix = "PM ";
            hours -= 12;
        }
        timeText.text = prefix + hours + ":" + minutes.ToString("00");
        //获取日期\星期
        int day = timestamp.day;
        string season = timestamp.season.ToString();
        string dayOfTheWeek = timestamp.GetDayOfTheWeek().ToString();

        dateText.text = season + " " + day + " (" + dayOfTheWeek +")";
    }
}

2、赋值

八、把时间系统运用到耕地上

1、编辑TimeManager.cs

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

public class TimeManager : MonoBehaviour
{
    public static TimeManager Instance { get; private set; }
    private void Awake()
    {
        if (Instance != null && Instance != this) { Destroy(this); }
        else { Instance = this; }
    }

    [SerializeField]
    GameTimestamp timestamp;
    public float timeScale = 1.0f;

    [Header("Day and Night cycle")]
    public Transform sunTransform;
    List<ITimeTracker> listeners = new List<ITimeTracker>();

    void Start()
    {
        timestamp = new GameTimestamp(0, GameTimestamp.Season.Spring, 1, 6, 0);
        StartCoroutine(TimeUpdate());
    }
    IEnumerator TimeUpdate()
    {
        while (true)
        {
            Tick();
            yield return new WaitForSeconds(1 / timeScale);
        }
    }
    public void Tick()
    {
        timestamp.UpdateClock();
        foreach (ITimeTracker listener in listeners)
        {
            listener.ClockUpdate(timestamp);
        }
        UpdateSunMovement();
    }

    void UpdateSunMovement()
    {
        int timeInMinutes = GameTimestamp.HoursToMinutes(timestamp.hour) + timestamp.minute;
        float sunAngle = .25f * timeInMinutes - 90;
        sunTransform.eulerAngles = new Vector3(sunAngle, 0, 0);
    }

    //获取新的时间戳
    public GameTimestamp GetGameTimestamp()
    {
        return new GameTimestamp(timestamp);
    }

    public void RegisterTracker(ITimeTracker listener)
    {
        listeners.Add(listener);
    }
    public void UnregisterTracker(ITimeTracker listener)
    {
        listeners.Remove(listener);
    }
}

2、编辑Land.cs,设置灌溉后土壤变化

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

//添加接口
public class Land : MonoBehaviour, ITimeTracker
{
    public enum LandStatus { Soil, Farmland, Watered }
    public LandStatus landStatus;
    public Material soilMat, farmlandMat, wateredMat;
    new Renderer renderer;

    public GameObject select;
    //灌溉时间
    GameTimestamp timeWatered;
    void Start()
    {
        renderer = GetComponent<Renderer>();
        SwitchLandStatus(LandStatus.Soil);
        //select.SetActive(false);
        Select(false);

        //注册时间戳
        TimeManager.Instance.RegisterTracker(this);
    }

    public void SwitchLandStatus(LandStatus statusToSwitch)
    {
        landStatus = statusToSwitch;
        Material materialToSwitch = soilMat;
        switch (statusToSwitch)
        {
            case LandStatus.Soil: materialToSwitch = soilMat; break;
            case LandStatus.Farmland: materialToSwitch = farmlandMat; break;
            //灌溉后土壤状态
            case LandStatus.Watered:
                materialToSwitch = wateredMat;
                //灌溉后流逝的时间
                timeWatered = TimeManager.Instance.GetGameTimestamp();
                break;
        }
        renderer.material = materialToSwitch;
    }
    public void Select(bool toggle)
    {
        select.SetActive(toggle);
    }

    public void Interact()
    {
        ItemData toolSlot = InventoryManager.Instance.equippedTool;
        EquipmentData equipmentTool = toolSlot as EquipmentData;
        if (equipmentTool != null)
        {
            EquipmentData.ToolType toolType = equipmentTool.toolType;

            switch (toolType)
            {
                case EquipmentData.ToolType.Hoe:
                    SwitchLandStatus(LandStatus.Farmland); break;
                case EquipmentData.ToolType.WateringCan:
                    SwitchLandStatus(LandStatus.Watered); break;
            }
        }
    }

    //设置灌溉后土壤的变化
    public void ClockUpdate(GameTimestamp timestamp)
    {
        if (landStatus == LandStatus.Watered)
        {
            int hoursElapsed = GameTimestamp.CompareTimestamp(timeWatered, timestamp);
            Debug.Log(hoursElapsed + "上次灌溉时间");

            if (hoursElapsed > 24)
            {
                SwitchLandStatus(LandStatus.Farmland);
            }
        }
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1984089.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【第三版 系统集成项目管理工程师】第10章 启动过程组

持续更新。。。。。。。。。。。。。。。 【第三版】第十章 启动过程组 10.1 制定项目章程10.1.1 主要输入1.立项管理文件-P3562.协议-P35710.1.2 主要输出1.项目章程-P3572.假设日志-P358练习10.2 识别干系人10.2.1 主要输入1.项目管理计划-P3602.项目文件-P36010.2.2 主要工…

49 mysql 子查询 加 group by 产生的奇怪现象

前言 这里要提到的是一个 之前碰到的一个 很令人诧异的查询, 主要是 和 group 查询有关系 查询如下, 按照常规理解, “select id from t_user_02 where name jerry group by age ” 会返回 两条数据, 然后 整个查询 会查询出两条数据 但是 结果很令人差异, 查询出了 四条…

华为云全域Serverless技术创新:全球首创通用Serverless平台被ACM SIGCOMM录用

华为开发者大会2024&#xff08;HDC 2024&#xff09;在东莞松山湖圆满结束&#xff0c;期间华为云主办的“全域Serverless时代&#xff1a;技术创新引领&#xff0c;赋能行业实践”专题论坛&#xff0c;向广大开发者传递了Serverless领域的前沿思考和实践&#xff0c;现场座无…

CVE-2023-33440详解

一.访问url http://eci-2zef9bcht3lq36hkwyoh.cloudeci1.ichunqiu.com/ 二.目录扫描 http://eci-2zef9bcht3lq36hkwyoh.cloudeci1.ichunqiu.com/ 三.拼接访问/login.php 四.抓包构造数据包 发给repeter 复制过去这几个位置都有空格&#xff0c;要删除掉&#xff0c;Referer和…

基于单片机的空调红外遥控器设计

【摘要】 本文基于单片机AT89C51、利用红外遥控发射技术设计了一款空调红外遥控器。对其系统结构框架、硬件部分等内容进行介绍&#xff0c;最后通过系统仿真验证设计的正确性和有效性。 【关键词】 遥控技术&#xff1b;单片机&#xff1b;红外 1.引言 远程控制技术指的是对…

DC系列靶场---DC 5靶场的渗透测试

DC-5渗透测试 信息收集 地址探测 使用arp-scan对目标主机进行地址探测 arp-scan -l -I eth0 目标主机IP地址为172.30.1.132 Nmap扫描 使用Nmap对目标主机进行端口扫描 nmap -sS -sV -T4 -p- -O 172.30.1.132//-sS Nmap默认扫描类型&#xff0c;SYS的秘密扫描//-sV 服务…

可用性测试:提升用户体验的关键

目录 前言1. 可用性测试的概念1.1 可用性测试的特点1.2 可用性测试的类型 2. 可用性测试的主要作用2.1 发现用户需求2.2 识别可用性问题2.3 提高用户满意度 3. 可用性测试在整个测试过程中的地位3.1 可用性测试与功能测试的关系3.2 可用性测试与性能测试的关系3.3 可用性测试与…

Java | Leetcode Java题解之第326题3的幂

题目&#xff1a; 题解&#xff1a; class Solution {public boolean isPowerOfThree(int n) {return n > 0 && 1162261467 % n 0;} }

鸿蒙(API 12 Beta2版)NDK开发【HarmonyOS ABI】硬件兼容性

HarmonyOS系统支持丰富的设备形态&#xff0c;支持多种架构指令集&#xff0c;支持多种操作系统内核&#xff1b;为了应用在各种HarmonyOS设备上的兼容性&#xff0c;本文定义了"OHOS" ABI&#xff08;Application Binary Interface&#xff09;的基础标准&#xff0…

《Milvus Cloud向量数据库指南》——高可用黄金标准:深入解析与业务策略考量

高可用黄金标准:深入解析与业务策略考量 在信息技术飞速发展的今天,高可用性(High Availability, HA)已成为衡量企业IT系统性能与稳定性的关键指标之一。它不仅仅关乎技术层面的优化与配置,更是企业保障业务连续性、提升客户体验、增强市场竞争力的重要基石。尽管高可用性…

基于Java中的SSM框架实现在线音乐网站系统项目【项目源码+论文说明】

基于Java中的SSM框架实现在线音乐网站系统演示 摘要 本文讲述了使用JSP语言及HTML5语言及MySql数据库技术开发的音乐网站的设计与实现。本文所讲的JSP音乐系统是通过所学的知识创办一个类似于QQ音乐或者酷狗音乐性质的网站平台&#xff0c;使所有对国内外音乐欣赏感兴趣的人都…

未授权访问漏洞合集

今天我们来开一个新的坑&#xff0c;未授权访问漏洞&#xff0c;以后我会慢慢更新&#xff0c;大家可以持续跟进一下&#xff0c;谢谢大家&#xff01; 未授权访问可以理解为需要安全配置或权限认证的地址、授权页面存在缺陷&#xff0c;导致其他用户可以直接访问&#xff0c;从…

卷积神经网络 - 结构化输出篇

序言 卷积神经网络&#xff08; CNN \text{CNN} CNN&#xff09;作为深度学习领域的重要分支&#xff0c;凭借其强大的特征提取与学习能力&#xff0c;在图像和视频处理领域取得了显著成就。其结构化输出的特性&#xff0c;更是为复杂任务的解决提供了有力支持。本文旨在简要概…

高德地图API-批量获取位置信息的经纬度

我们会遇到一些需要批量把地址数据转换成坐标的问题&#xff0c;一个个查的话通常会比较麻烦&#xff0c;那有没有比较方便的方法呢&#xff0c;我们可以利用高德的地理编码/逆地理编码 API功能&#xff0c; 通过 HTTP/HTTPS 协议访问远程服务的接口&#xff0c;提供结构化地址…

渗透课程练习

第一步进入网站软件&#xff0c;启动Apache和Mysql&#xff0c;这里出了点小插曲&#xff0c;电脑自身的mysl如果没有停止运行就无法启动mysql&#xff0c;找到“服务”后进入寻找mysql停止运行。 第一关 get传参浏览器中输入&#xff1f;id1 创建价格表 修改php的文件后重新输…

MySQL 5.7使用 GTID 和 Binlog高可用方案

文章目录 介绍GTID和Binlog的关系GTID&#xff08;Global Transaction ID&#xff09;Binlog&#xff08;二进制日志&#xff09; MySQL5.7基于yum搭建安装 MySQL初始化并设置远程登录密码 配置基于GTID的复制模式第一台主服务器配置主服务器配置启动从服务 第二台主服务器配置…

【Linux学习】文件系统 - 第三篇

&#x1f351;个人主页&#xff1a;Jupiter. &#x1f680; 所属专栏&#xff1a;Linux从入门到进阶 欢迎大家点赞收藏评论&#x1f60a; 目录 &#x1f985;重定向原理以及实现&#x1f431;dup2系统调用实现重定向。&#x1f388;dup2 系统调用&#x1f351;在自定义shell中实…

MM 10 -采购- 标准采购订单

思维导图 说明 采购订单页面介绍 抬头 支付、开票&#xff1a; 付款条件 文本&#xff1a; 机构数据&#xff1a; 其余sheet不常用 行项目 物料 数量 交货日期 价格 &#xff1a;信息记录带出来 工厂 行项目明细 物料 供应商物料号 供应商子范围&#xff1a; 批次&a…

PXE安装配置(rhel7)

实验需求&#xff1a; rhel7 虚拟机 所需软件安装&#xff1a; sudo yum install -y dhcp tftp-server httpd syslinux system-config-kickstart 启动&#xff1a; system-config-kickstart 制作ks文件 注意&#xff1a;File----Save保存一下 打开root下的ks.cfg在分区信…

python:将 NWPU_VHR-10 遥感目标检测数据集转换成 YOLO 格式

作者&#xff1a;CSDN _养乐多_ 本文将介绍将 NWPU_VHR-10 遥感目标检测数据集转换成 YOLO 格式的 python 脚本。 文章目录 一、数据集介绍1.1 数据集下载1.2 数据集介绍1.3 数据格式 二、格式转换三、完整代码 一、数据集介绍 1.1 数据集下载 https://opendatalab.com/Ope…