第一个velocity碰到的问题及解决

本文介绍了一个简单的HelloVelocity示例程序及其遇到的问题:运行时出现NoClassDefFoundError错误。文章分析了错误原因并指出缺少velocity-dep-1.5.jar依赖导致ExtendedProperties类未被加载。

文件目录结构:

源程序很简单,就是在网上看到的HelloVelocity如下:
vm为:           Welcome $name to wuweishe.blogchina.com!
java文件为:      import java.io.StringWriter;

import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;


public class HelloVelocity
{
    public static void main(String[] args) throws Exception
    {
        /*  first, get and initialize an engine  */
        VelocityEngine engine = new VelocityEngine();
        engine.init();

        /*  next, get the Template  */
        Template template = engine.getTemplate( "hellovelocity.vm" );

        /*  create a context and add data */
        VelocityContext context = new VelocityContext();
        context.put("name", "World");

        /* now render the template into a StringWriter */
        StringWriter writer = new StringWriter();
        template.merge( context, writer );

        /* display the results */
        System.out.println( writer.toString() );    
    }    
}

编译能通过但运行时提示:
  Exception in thread "main"       java.lang.NoClassDefFoundError:org/apache/commons/collections/ExtendedProperties
at org.apache.velocity.runtime.RuntimeInstance.<init><RuntimeInstance.java:160>
at org.apache.velocity.app.VelocityEngine.<init><VelocityEngine.java:71>
at HelloVelocity.main(HelloVelocity.java:13)
 

可以看出,是org.apache.commons.collections.ExtendedProperties没有加载进去啊,

这个类应该在velocity-dep-1.5.jar下面,所以你肯定没有把velocity-dep-1.5.jar加载到你的类中.

 

### 🛠 教你一步步解决这个问题 --- #### ✅ 第一步:理解你遇到了什么问题 你的问题是在游戏中,角色无法正常移动和跳跃,并提示: > **“无法通过接口访问数值,因为该数值位于继承自 ScriptableObject 的数值容器中,而非 MonoBehaviour 组件。”** 这意味着:**游戏运行时,角色尝试读取“移动速度”和“跳跃力”这些属性时,找不到可用的运行时数值。** --- #### ✅ 第二步:准备“运行时数据容器” 为了让角色在游戏运行时能读取这些数值,我们需要给角色创建一个“临时数据本”: ```csharp // RuntimeCharacterData.cs public class RuntimeCharacterData { public CharacterStats BaseStats { get; private set; } // 原始数据(菜谱) public float CurrentMoveSpeed { get; set; } // 实际用的速度 public float CurrentJumpForce { get; set; } // 实际用的跳跃力 public bool IsMovementLocked { get; set; } // 是否被锁定移动 public RuntimeCharacterData(CharacterStats baseStats) { BaseStats = baseStats; ResetToBaseStats(); } public void ResetToBaseStats() { CurrentMoveSpeed = BaseStats.moveSpeed; CurrentJumpForce = BaseStats.jumpForce; IsMovementLocked = false; } } ``` 👉 在 Unity 项目的 `Assets/Scripts` 文件夹中创建这个文件。 --- #### ✅ 第三步:修改角色基类,使用这个运行时数据 ```csharp // CharacterBase.cs public abstract class CharacterBase : MonoBehaviour { [SerializeField] private CharacterStats _baseStats; private RuntimeCharacterData _runtimeData; public RuntimeCharacterData RuntimeData => _runtimeData; void Start() { _runtimeData = new RuntimeCharacterData(_baseStats); if (_baseStats != null && !_baseStats.Validate()) { Debug.LogError($"{name} 使用的属性文件不合法!", this); } } public void TakeDamage(int damage, ElementType element) { _runtimeData.BaseStats.baseHealth -= damage; } } ``` 👉 把原来的 `CharacterStats` 字段换成这个结构,这样角色就有运行时的数据了。 --- #### ✅ 第四步:更新移动控制器 ```csharp // PlayerMovement.cs public class PlayerMovement : MonoBehaviour, IMovable { private RuntimeCharacterData _runtimeData; private Rigidbody2D _rb; private CharacterBase _character; void Start() { _rb = GetComponent<Rigidbody2D>(); _character = GetComponent<CharacterBase>(); if (_character != null) { _runtimeData = _character.RuntimeData; } else { Debug.LogError("找不到 CharacterBase 组件", this); } } public void Move(Vector2 direction) { if (_runtimeData.IsMovementLocked) return; float speed = _runtimeData.CurrentMoveSpeed; _rb.velocity = new Vector2(direction.x * speed, _rb.velocity.y); } public void Jump() { if (!IsGrounded || _runtimeData.IsMovementLocked) return; float jumpForce = _runtimeData.CurrentJumpForce; _rb.AddForce(Vector2.up * jumpForce, ForceMode2D.Impulse); } public void SetMovementLock(bool locked) { _runtimeData.IsMovementLocked = locked; if (locked) { _rb.velocity = new Vector2(0, _rb.velocity.y); } } } ``` 👉 所有地方从 `_runtimeData` 获取数值,而不是直接从 `CharacterStats`。 --- #### ✅ 第五步:确保角色预制体配置正确 1. **角色必须有以下组件**: - `CharacterBase` - `PlayerMovement` - `Rigidbody2D` 2. **CharacterBase 必须分配 `CharacterStats` 数据资产**。 3. **PlayerMovement 必须能访问到 `Rigidbody2D` 和 `CharacterBase`**。 --- #### ✅ 第六步:临时补救方案(不想改结构时用) 如果不想改动太多结构,可以先在 `PlayerMovement.cs` 里临时写死数值: ```csharp public void Move(Vector2 direction) { float speed = 5f; // 临时写死 _rb.velocity = new Vector2(direction.x * speed, _rb.velocity.y); } public void Jump() { float jumpForce = 10f; // 临时写死 _rb.AddForce(Vector2.up * jumpForce, ForceMode2D.Impulse); } ``` --- #### ✅ 第七步:测试和调试 1. **运行游戏**,看角色是否能移动、跳跃。 2. **打开调试信息**(可选): ```csharp void OnGUI() { GUILayout.Label($"速度: {_runtimeData.CurrentMoveSpeed}"); GUILayout.Label($"跳跃力: {_runtimeData.CurrentJumpForce}"); GUILayout.Label($"是否锁定移动: {_runtimeData.IsMovementLocked}"); } ``` 3. **检查控制台是否有错误信息**。 --- ### ✅ 总结一下,你需要做的几步: | 步骤 | 内容 | |------|------| | 1 | 创建 `RuntimeCharacterData` 类,作为运行时数据容器 | | 2 | 修改 `CharacterBase` 使用这个运行时数据 | | 3 | 修改 `PlayerMovement` 从运行时数据读取数值 | | 4 | 确保角色预制体有正确的组件和引用 | | 5 | 测试功能是否恢复,或使用临时写死方案 | --- 如果你卡在某一步,欢迎继续问我,我可以手把手带你改代码!
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值